From 10775040ca697316d4d39da9c24089f04277f8b7 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 5 May 2026 09:25:18 +0000 Subject: [PATCH] Implement component core type system Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- src/parser/WASMComponentParser.cpp | 152 +++++++++++++++++- src/runtime/Component.h | 104 +++++++++++- src/runtime/Module.h | 4 +- src/runtime/ObjectType.h | 21 +++ third_party/wabt/include/wabt/binary.h | 1 + third_party/wabt/include/wabt/component.h | 1 + .../wabt/include/wabt/shared-validator.h | 27 +++- third_party/wabt/include/wabt/type-checker.h | 3 +- .../wabt/walrus/binary-reader-walrus.h | 5 +- third_party/wabt/src/binary-reader.cc | 15 +- third_party/wabt/src/binary-writer.cc | 3 + third_party/wabt/src/component.cc | 4 + third_party/wabt/src/shared-validator.cc | 103 +++++++++--- third_party/wabt/src/stream.cc | 15 +- third_party/wabt/src/type-checker.cc | 26 ++- .../wabt/src/walrus/binary-reader-walrus.cc | 18 ++- third_party/wabt/src/wast-parser.cc | 3 + 17 files changed, 441 insertions(+), 64 deletions(-) diff --git a/src/parser/WASMComponentParser.cpp b/src/parser/WASMComponentParser.cpp index 634c91fa9..b0f8efd69 100644 --- a/src/parser/WASMComponentParser.cpp +++ b/src/parser/WASMComponentParser.cpp @@ -16,6 +16,7 @@ #include "Walrus.h" #include "parser/WASMComponentParser.h" +#include "parser/WASMParser.h" #include "runtime/Store.h" #include "runtime/TypeStore.h" @@ -26,6 +27,26 @@ namespace wabt { class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate { private: + struct CoreInstanceType { + static constexpr size_t NotInline = ~static_cast(0); + + CoreInstanceType(Walrus::Module* module) + : module(module) + , inlineIndex(NotInline) + { + ASSERT(module != nullptr); + } + + CoreInstanceType(size_t inlineIndex) + : module(nullptr) + , inlineIndex(inlineIndex) + { + } + + Walrus::Module* module; + size_t inlineIndex; + }; + // Depth data for each component. struct ComponentTypeInfo { ComponentTypeInfo(ComponentTypeInfo* parent, Walrus::ComponentType* parentComponentType, Walrus::Component* parentComponent) @@ -38,6 +59,10 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate ComponentTypeInfo* parent; Walrus::ComponentType* parentComponentType; Walrus::Component* parentComponent; + std::vector coreFuncTypes; + std::vector coreMemories; + std::vector coreModuleTypes; + std::vector coreInstanceTypes; std::vector funcTypes; std::vector componentTypes; std::vector instanceTypes; @@ -223,8 +248,11 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate } public: - WASMComponentBinaryReader(Walrus::TypeStore& typeStore) - : m_typeStore(typeStore) + WASMComponentBinaryReader(Walrus::Store* store, const std::string& filename, const uint32_t JITFlags, const uint32_t featureFlags) + : m_store(store) + , m_filename(filename) + , m_JITFlags(JITFlags) + , m_featureFlags(featureFlags) , m_current(nullptr) , m_currentComponent(nullptr) , m_currentInfo(nullptr) @@ -240,10 +268,28 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate } } + const std::string& filename() + { + return m_filename; + } + + uint32_t featureFlags() + { + return m_featureFlags; + } + void OnCoreModule(const void* data, size_t size, const ReadBinaryOptions& options) { + std::pair, std::string> result = Walrus::WASMParser::parseBinary(m_store, m_filename, reinterpret_cast(data), size, m_JITFlags, m_featureFlags); + if (!result.second.empty()) { + m_walrusParseError = result.second; + } + // Module has been already added to store. + Walrus::Module* module = result.first.value(); + m_currentComponent->pushDeclaration(new Walrus::ComponentCoreModule(module)); + m_currentInfo->coreModuleTypes.push_back(module); } void BeginComponent(uint32_t version, size_t depth) @@ -276,12 +322,16 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void BeginCoreInstance(Index moduleIndex, uint32_t argumentCount) { + m_currentInfo->coreInstanceTypes.push_back(CoreInstanceType(m_currentInfo->coreModuleTypes[moduleIndex])); + m_currentComponent->pushDeclaration(new Walrus::ComponentCoreInstantiate(moduleIndex)); } void OnCoreInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) { + Walrus::ComponentCoreInstantiate* instance = m_currentComponent->declarations().back()->asCoreInstantiate(); + instance->arguments().push_back(Walrus::ComponentCoreInstantiate::Argument{ name.str.to_string(), index }); } void EndCoreInstance() @@ -290,16 +340,59 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate void BeginInlineCoreInstance(uint32_t argumentCount) { + m_currentInfo->coreInstanceTypes.push_back(CoreInstanceType(m_currentComponent->declarations().size())); + m_currentComponent->pushDeclaration(new Walrus::ComponentCoreInstantiateInline()); + ASSERT(m_names.size() == 0); } void OnInlineCoreInstanceArg(const ComponentStringLoc& name, ComponentSort sort, Index index) { + Walrus::ComponentCoreInstantiateInline* instance = m_currentComponent->declarations().back()->asCoreInstantiateInline(); + instance->arguments().push_back(Walrus::ComponentCoreInstantiateInline::Argument{ getSort(sort), index }); + m_names.push_back(name.str.to_string()); } void EndInlineCoreInstance() { + Walrus::ComponentCoreInstantiateInline* instance = m_currentComponent->declarations().back()->asCoreInstantiateInline(); + Walrus::WASMParsingResult result; + size_t size = instance->arguments().size(); + uint32_t funcIndex = 0; + uint32_t tableIndex = 0; + uint32_t memoryIndex = 0; + uint32_t globalIndex = 0; + ASSERT(m_names.size() == size); + + for (size_t i = 0; i < size; i++) { + Walrus::ExportType::Type exportType; + uint32_t index; + switch (instance->arguments()[i].sort) { + case Walrus::ComponentSort::CoreFunc: + index = funcIndex++; + exportType = Walrus::ExportType::Function; + break; + case Walrus::ComponentSort::CoreTable: + index = tableIndex++; + exportType = Walrus::ExportType::Table; + break; + case Walrus::ComponentSort::CoreMemory: + index = memoryIndex++; + exportType = Walrus::ExportType::Memory; + break; + default: + ASSERT(instance->arguments()[i].sort == Walrus::ComponentSort::CoreGlobal); + index = globalIndex++; + exportType = Walrus::ExportType::Global; + break; + } + result.m_exports.push_back(new Walrus::ExportType(exportType, m_names[i], index)); + } + Walrus::Module* module = new Walrus::Module(m_store, result); + m_currentInfo->coreInstanceTypes.back().module = module; + instance->setModule(module); + m_names.clear(); } void BeginInstance(Index componentIndex, @@ -378,6 +471,50 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate Index coreInstanceIndex, const ComponentStringLoc& name) { + size_t exportIndex = 0; + const CoreInstanceType& type = m_currentInfo->coreInstanceTypes[coreInstanceIndex]; + const Walrus::VectorWithFixedSize>& exports = type.module->exports(); + + while (true) { + if (exportIndex >= exports.size()) { + m_walrusParseError = "export not found"; + return; + } + + if (name.str == exports[exportIndex]->name()) { + break; + } + exportIndex++; + } + + if (type.inlineIndex != CoreInstanceType::NotInline) { + exportIndex = m_currentComponent->declarations()[type.inlineIndex]->asCoreInstantiateInline()->arguments()[exportIndex].index; + + switch (sort) { + case ComponentSort::CoreFunc: + m_currentInfo->coreFuncTypes.push_back(m_currentInfo->coreFuncTypes[exportIndex]); + break; + case ComponentSort::CoreMemory: + m_currentInfo->coreMemories.push_back(m_currentInfo->coreMemories[exportIndex]); + break; + default: + break; + } + return; + } + + uint32_t itemIndex = exports[exportIndex]->itemIndex(); + + switch (sort) { + case ComponentSort::CoreFunc: + m_currentInfo->coreFuncTypes.push_back(type.module->function(itemIndex)->functionType()); + break; + case ComponentSort::CoreMemory: + m_currentInfo->coreMemories.push_back(type.module->memoryType(itemIndex)->is64()); + break; + default: + break; + } } void OnAliasOuter(ComponentSort sort, @@ -669,10 +806,15 @@ class WASMComponentBinaryReader : public wabt::WASMComponentBinaryReaderDelegate } private: - Walrus::TypeStore& m_typeStore; + Walrus::Store* m_store; + std::string m_filename; + uint32_t m_JITFlags; + uint32_t m_featureFlags; + Walrus::ComponentType* m_current; Walrus::Component* m_currentComponent; ComponentTypeInfo* m_currentInfo; + std::vector m_names; }; } // namespace wabt @@ -681,9 +823,9 @@ namespace Walrus { std::pair, std::string> WASMComponentParser::parseBinary(Store* store, const std::string& filename, const uint8_t* data, size_t len, const uint32_t JITFlags, const uint32_t featureFlags) { - wabt::WASMComponentBinaryReader delegate(store->getTypeStore()); + wabt::WASMComponentBinaryReader delegate(store, filename, JITFlags, featureFlags); - std::string error = ReadWasmComponentBinary(filename, data, len, &delegate, featureFlags); + std::string error = ReadWasmComponentBinary(data, len, &delegate); if (error.length()) { return std::make_pair(nullptr, error); } diff --git a/src/runtime/Component.h b/src/runtime/Component.h index 2058fc7a8..01300f402 100644 --- a/src/runtime/Component.h +++ b/src/runtime/Component.h @@ -589,6 +589,9 @@ class CanonicalOptions { uint32_t m_callbackIndex; }; +class ComponentCoreModule; +class ComponentCoreInstantiate; +class ComponentCoreInstantiateInline; class ComponentInstantiate; class ComponentInstantiateInline; class ComponentCanonLift; @@ -598,7 +601,9 @@ class ComponentCanonType; class ComponentDeclaration { public: enum Kind : uint8_t { - ComponentKind, + CoreModuleKind, + CoreInstantiateKind, + CoreInstantiateInlineKind, InstantiateKind, InstantiateInlineKind, CanonLiftKind, @@ -607,6 +612,7 @@ class ComponentDeclaration { CanonResourceDrop, CanonResourceRep, ImportKind, + ComponentKind, }; ComponentDeclaration(Kind kind) @@ -621,6 +627,24 @@ class ComponentDeclaration { return m_kind; } + ComponentCoreModule* asCoreModule() + { + ASSERT(kind() == CoreModuleKind); + return reinterpret_cast(this); + } + + ComponentCoreInstantiate* asCoreInstantiate() + { + ASSERT(kind() == CoreInstantiateKind); + return reinterpret_cast(this); + } + + ComponentCoreInstantiateInline* asCoreInstantiateInline() + { + ASSERT(kind() == CoreInstantiateInlineKind); + return reinterpret_cast(this); + } + ComponentInstantiate* asInstantiate() { ASSERT(kind() == InstantiateKind); @@ -660,6 +684,84 @@ class ComponentDeclaration { Kind m_kind; }; +class ComponentCoreModule : public ComponentDeclaration { +public: + ComponentCoreModule(Module* module) + : ComponentDeclaration(CoreModuleKind) + , m_module(module) + { + } + + Module* module() + { + return m_module; + } + +private: + Module* m_module; +}; + +class ComponentCoreInstantiate : public ComponentDeclaration { +public: + struct Argument { + std::string name; + uint32_t index; + }; + + ComponentCoreInstantiate(uint32_t moduleIndex) + : ComponentDeclaration(CoreInstantiateKind) + , m_moduleIndex(moduleIndex) + { + } + + uint32_t moduleIndex() + { + return m_moduleIndex; + } + + std::vector& arguments() + { + return m_arguments; + } + +private: + uint32_t m_moduleIndex; + std::vector m_arguments; +}; + +class ComponentCoreInstantiateInline : public ComponentDeclaration { +public: + struct Argument { + ComponentSort sort; + uint32_t index; + }; + + ComponentCoreInstantiateInline() + : ComponentDeclaration(CoreInstantiateInlineKind) + , m_module(nullptr) + { + } + + Module* module() + { + return m_module; + } + + void setModule(Module* module) + { + m_module = module; + } + + std::vector& arguments() + { + return m_arguments; + } + +private: + Module* m_module; + std::vector m_arguments; +}; + class ComponentInstantiate : public ComponentDeclaration { public: struct Argument { diff --git a/src/runtime/Module.h b/src/runtime/Module.h index 11f58b685..d4bb45cc3 100644 --- a/src/runtime/Module.h +++ b/src/runtime/Module.h @@ -22,7 +22,8 @@ namespace wabt { class WASMBinaryReader; -} +class WASMComponentBinaryReader; +} // namespace wabt namespace Walrus { @@ -344,6 +345,7 @@ class Element { class Module : public Object { friend class wabt::WASMBinaryReader; + friend class wabt::WASMComponentBinaryReader; friend class JITCompiler; friend class Store; diff --git a/src/runtime/ObjectType.h b/src/runtime/ObjectType.h index eab215ad2..796ae1c1e 100644 --- a/src/runtime/ObjectType.h +++ b/src/runtime/ObjectType.h @@ -27,6 +27,9 @@ class FunctionType; class StructType; class ArrayType; class RecursiveType; +class GlobalType; +class TableType; +class MemoryType; class ObjectType { public: @@ -45,6 +48,24 @@ class ObjectType { Kind kind() const { return m_kind; } + GlobalType* asGlobalType() + { + ASSERT(kind() == ObjectType::GlobalKind); + return reinterpret_cast(this); + } + + TableType* asTableType() + { + ASSERT(kind() == ObjectType::TableKind); + return reinterpret_cast(this); + } + + MemoryType* asMemoryType() + { + ASSERT(kind() == ObjectType::MemoryKind); + return reinterpret_cast(this); + } + protected: ObjectType(Kind kind) : m_kind(kind) diff --git a/third_party/wabt/include/wabt/binary.h b/third_party/wabt/include/wabt/binary.h index 23c37cf67..d6a19210b 100644 --- a/third_party/wabt/include/wabt/binary.h +++ b/third_party/wabt/include/wabt/binary.h @@ -119,6 +119,7 @@ enum class ComponentBinaryCoreSort : uint8_t { Table = 0x01, Memory = 0x02, Global = 0x03, + Tag = 0x04, Type = 0x10, Module = 0x11, Instance = 0x12, diff --git a/third_party/wabt/include/wabt/component.h b/third_party/wabt/include/wabt/component.h index 72698dcf5..1a0d7017f 100644 --- a/third_party/wabt/include/wabt/component.h +++ b/third_party/wabt/include/wabt/component.h @@ -44,6 +44,7 @@ class ComponentSort { CoreTable, CoreMemory, CoreGlobal, + CoreTag, CoreType, CoreModule, CoreInstance, diff --git a/third_party/wabt/include/wabt/shared-validator.h b/third_party/wabt/include/wabt/shared-validator.h index 812120af3..4e4f6cd5f 100644 --- a/third_party/wabt/include/wabt/shared-validator.h +++ b/third_party/wabt/include/wabt/shared-validator.h @@ -548,7 +548,6 @@ class SharedComponentValidator { Component, Func, Resource, - ResourceAsync, }; // Checks may ignore the last (partly created) item of a sort. @@ -570,6 +569,7 @@ class SharedComponentValidator { struct TypeItems; struct TypeTuple; struct TypeLabels; + struct TypeResource; struct TypeFunc; struct TypeExternalList; @@ -595,7 +595,7 @@ class SharedComponentValidator { } bool IsValueTypePair() const { - return type_def == TypeDef::Result || type_def == TypeDef::ResourceAsync; + return type_def == TypeDef::Result; } ValueTypePair* AsValueTypePair() { @@ -626,6 +626,11 @@ class SharedComponentValidator { return reinterpret_cast(this); } + TypeResource* AsTypeResource() { + assert(type_def == TypeDef::Resource); + return reinterpret_cast(this); + } + bool IsTypeFunc() const { return type_def == TypeDef::Func || type_def == TypeDef::AsyncFunc; } @@ -734,6 +739,19 @@ class SharedComponentValidator { std::vector items; }; + struct TypeResource : public TypeBase { + enum Type : uint8_t { + Local, + LocalAsync, + Imported, + }; + + TypeResource(Type type) + : TypeBase(TypeDef::Resource), type(type) {} + + Type type; + }; + struct TypeFunc : public TypeBase { struct Param { const std::string* name; @@ -788,7 +806,12 @@ class SharedComponentValidator { // Sorts. TypeBaseVector core_funcs; + uint32_t core_tables = 0; TypeBaseVector core_memories; + uint32_t core_globals = 0; + uint32_t core_tags = 0; + uint32_t core_types = 0; + TypeBaseVector core_instances; TypeBaseVector core_modules; TypeBaseVector funcs; TypeBaseVector components; diff --git a/third_party/wabt/include/wabt/type-checker.h b/third_party/wabt/include/wabt/type-checker.h index 53b7deeaf..6f0dd5f4c 100644 --- a/third_party/wabt/include/wabt/type-checker.h +++ b/third_party/wabt/include/wabt/type-checker.h @@ -217,7 +217,8 @@ class TypeChecker { Result OnReturnCall(const TypeVector& param_types, const TypeVector& result_types); Result OnReturnCallIndirect(const TypeVector& param_types, - const TypeVector& result_types); + const TypeVector& result_types, + const Limits& table_limits); Result OnReturnCallRef(Type type, const TypeVector& param_types, const TypeVector& result_types); 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 d1ed45bb4..665385e38 100644 --- a/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h +++ b/third_party/wabt/include/wabt/walrus/binary-reader-walrus.h @@ -249,6 +249,9 @@ class WASMComponentBinaryReaderDelegate { public: virtual ~WASMComponentBinaryReaderDelegate() {} + virtual const std::string& filename() = 0; + virtual uint32_t featureFlags() = 0; + virtual void OnCoreModule(const void* data, size_t size, const ReadBinaryOptions& options) = 0; @@ -367,7 +370,7 @@ enum FeatureFlagValue : uint32_t { }; std::string ReadWasmBinary(const std::string& filename, const uint8_t *data, size_t size, WASMBinaryReaderDelegate* delegate, const uint32_t featureFlags); -std::string ReadWasmComponentBinary(const std::string& filename, const uint8_t *data, size_t size, WASMComponentBinaryReaderDelegate* delegate, const uint32_t featureFlags); +std::string ReadWasmComponentBinary(const uint8_t *data, size_t size, WASMComponentBinaryReaderDelegate* delegate); } // namespace wabt diff --git a/third_party/wabt/src/binary-reader.cc b/third_party/wabt/src/binary-reader.cc index ea82f5b94..3996883cb 100644 --- a/third_party/wabt/src/binary-reader.cc +++ b/third_party/wabt/src/binary-reader.cc @@ -215,7 +215,7 @@ class BinaryReader { [[nodiscard]] Result ReadComponentCoreInstance(); [[nodiscard]] Result ReadComponentInstance(); [[nodiscard]] Result ReadComponentInlineInstance(); - [[nodiscard]] Result ReadComponentAlias(bool is_component); + [[nodiscard]] Result ReadComponentAlias(); [[nodiscard]] Result ReadComponentValType(ComponentTypeLoc* out_type); [[nodiscard]] Result ReadComponentValTypeOpt(ComponentTypeLoc* out_type); [[nodiscard]] Result ReadComponentType(); @@ -2938,6 +2938,10 @@ Result BinaryReader::ReadTypeSection(Offset section_size) { supertypes.is_final_sub_type = (form == Type::SubFinal); CHECK_RESULT( ReadU32Leb128(&supertypes.sub_type_count, "sub type count")); + // Currently validator limits this value to 1. + ERROR_UNLESS(supertypes.sub_type_count < 65536, + "too many subtypes (%" PRIindex ")", + supertypes.sub_type_count); sub_types_.resize(supertypes.sub_type_count); for (Index i = 0; i < supertypes.sub_type_count; i++) { @@ -3604,6 +3608,9 @@ Result BinaryReader::ReadComponentCoreSort(ComponentSort* out_sort) { case ComponentBinaryCoreSort::Global: *out_sort = ComponentSort::CoreGlobal; break; + case ComponentBinaryCoreSort::Tag: + *out_sort = ComponentSort::CoreTag; + break; case ComponentBinaryCoreSort::Type: *out_sort = ComponentSort::CoreType; break; @@ -3784,7 +3791,7 @@ Result BinaryReader::ReadComponentInlineInstance() { return Result::Ok; } -Result BinaryReader::ReadComponentAlias(bool is_component) { +Result BinaryReader::ReadComponentAlias() { ComponentSort sort; CHECK_RESULT(ReadComponentSort(&sort)); @@ -4134,7 +4141,7 @@ Result BinaryReader::ReadComponentType() { case ComponentBinaryInterface::Type: break; case ComponentBinaryInterface::Alias: - CHECK_RESULT(ReadComponentAlias(false)); + CHECK_RESULT(ReadComponentAlias()); continue; case ComponentBinaryInterface::Import: CHECK_RESULT(ReadComponentExternal(true, false)); @@ -4409,7 +4416,7 @@ Result BinaryReader::ReadComponent() { COMPONENT_CALLBACK(BeginAliasSection, count); while (count > 0) { - CHECK_RESULT(ReadComponentAlias(true)); + CHECK_RESULT(ReadComponentAlias()); count--; } COMPONENT_CALLBACK0(EndAliasSection); diff --git a/third_party/wabt/src/binary-writer.cc b/third_party/wabt/src/binary-writer.cc index f8160e057..439612f3e 100644 --- a/third_party/wabt/src/binary-writer.cc +++ b/third_party/wabt/src/binary-writer.cc @@ -2182,6 +2182,9 @@ void BinaryWriter::WriteComponentSort(ComponentSort sort, bool core_only) { case ComponentSort::CoreGlobal: core_code = ComponentBinaryCoreSort::Global; break; + case ComponentSort::CoreTag: + core_code = ComponentBinaryCoreSort::Tag; + break; case ComponentSort::CoreType: core_code = ComponentBinaryCoreSort::Type; break; diff --git a/third_party/wabt/src/component.cc b/third_party/wabt/src/component.cc index 574feb9ed..2ab1b902a 100644 --- a/third_party/wabt/src/component.cc +++ b/third_party/wabt/src/component.cc @@ -63,6 +63,8 @@ const char* ComponentSort::GetName() const { return "core memory"; case CoreGlobal: return "core global"; + case CoreTag: + return "core tag"; case CoreType: return "core type"; case CoreModule: @@ -94,6 +96,8 @@ const char* ComponentSort::GetCoreName() const { return "memory"; case CoreGlobal: return "global"; + case CoreTag: + return "tag"; case CoreType: return "type"; case CoreModule: diff --git a/third_party/wabt/src/shared-validator.cc b/third_party/wabt/src/shared-validator.cc index 8dec27eb7..7a1a768df 100644 --- a/third_party/wabt/src/shared-validator.cc +++ b/third_party/wabt/src/shared-validator.cc @@ -1596,8 +1596,8 @@ Result SharedValidator::OnReturnCallIndirect(const Location& loc, "type mismatch: return_call_indirect must reference " "table of funcref type"); } - result |= - typechecker_.OnReturnCallIndirect(func_type.params, func_type.results); + result |= typechecker_.OnReturnCallIndirect( + func_type.params, func_type.results, table_type.limits); IgnoreLocalRefs(); return result; } @@ -1945,9 +1945,13 @@ Result SharedComponentValidator::EndComponent() { Result SharedComponentValidator::OnCoreInstance( const ComponentIndexLoc& module_index, uint32_t argument_count) { + TypeBase* type_base = nullptr; + Result result = + CheckIndex(ComponentSort::CoreModule, module_index, &type_base); + CurrentAsComponent()->core_instances.push_back(type_base); assert(caseful_names_.empty()); argument_count_ = argument_count; - return Result::Ok; + return result; } Result SharedComponentValidator::OnCoreInstanceArg( @@ -1979,6 +1983,10 @@ Result SharedComponentValidator::OnCoreInstanceArg( } Result SharedComponentValidator::OnInlineCoreInstance(uint32_t argument_count) { + Component* component = CurrentAsComponent(); + auto module = MakeUnique(); + component->core_instances.push_back(module.get()); + objects_.push_back(std::move(module)); assert(caseful_names_.empty()); argument_count_ = argument_count; return Result::Ok; @@ -2159,9 +2167,10 @@ Result SharedComponentValidator::OnAliasCoreExport( ComponentSort sort, const ComponentIndexLoc& core_instance_index, const ComponentStringLoc& name) { - if (sort != ComponentSort::CoreFunc && sort != ComponentSort::CoreTable && - sort != ComponentSort::CoreMemory && sort != ComponentSort::CoreGlobal && - sort != ComponentSort::CoreType) { + if ((current_->info_bits & IsObject) == 0 || + (sort != ComponentSort::CoreFunc && sort != ComponentSort::CoreTable && + sort != ComponentSort::CoreMemory && sort != ComponentSort::CoreGlobal && + sort != ComponentSort::CoreTag)) { return PrintError(loc, "invalid alias core export sort (%s)", sort.GetName()); } @@ -2170,11 +2179,22 @@ Result SharedComponentValidator::OnAliasCoreExport( Result result = CheckIndex(ComponentSort::CoreInstance, core_instance_index, &type_base); - type_base = nullptr; - - TypeBaseVector* type_vector = GetSort(current_, sort); - if (type_vector != nullptr) { - type_vector->push_back(type_base); + switch (sort) { + case ComponentSort::CoreTable: + CurrentAsComponent()->core_tables++; + break; + case ComponentSort::CoreGlobal: + CurrentAsComponent()->core_globals++; + break; + case ComponentSort::CoreTag: + CurrentAsComponent()->core_tags++; + break; + default: { + type_base = nullptr; + TypeBaseVector* type_vector = GetSort(current_, sort); + assert(type_vector != nullptr); + type_vector->push_back(type_base); + } } return result; } @@ -2483,7 +2503,7 @@ Result SharedComponentValidator::OnResourceType(const Location& loc, result |= PrintError(loc, "resources can only be defined in concrete components"); } - auto type_value = MakeUnique(TypeDef::Resource); + auto type_value = MakeUnique(TypeResource::Local); type_value->info_bits |= HasResource; current_->types.push_back(type_value.get()); objects_.push_back(std::move(type_value)); @@ -2500,7 +2520,7 @@ Result SharedComponentValidator::OnResourceAsyncType( result |= PrintError(loc, "resources can only be defined in concrete components"); } - auto type_value = MakeUnique(TypeDef::ResourceAsync); + auto type_value = MakeUnique(TypeResource::LocalAsync); type_value->info_bits |= HasResource; current_->types.push_back(type_value.get()); objects_.push_back(std::move(type_value)); @@ -2572,6 +2592,26 @@ Result SharedComponentValidator::OnCanonLower( Result SharedComponentValidator::OnCanonType( ComponentCanon canon, const ComponentIndexLoc& type_index) { + Result result = Result::Ok; + switch (canon) { + case ComponentCanon::ResourceNew: + case ComponentCanon::ResourceDrop: + case ComponentCanon::ResourceRep: { + TypeBase* type_base = nullptr; + result |= CheckIndex(type_index.loc, ComponentSort::Type, + type_index.index, IncludeLast, &type_base); + result |= CheckResource(type_index.loc, &type_base); + // The type_base is set to nullptr on error. + if (canon != ComponentCanon::ResourceDrop && type_base != nullptr && + type_base->AsTypeResource()->type == TypeResource::Imported) { + result |= + PrintError(type_index.loc, "resource must be defined locally"); + } + break; + } + default: + break; + } auto type_value = MakeUnique(TypeDef::CoreFunc); CurrentAsComponent()->core_funcs.push_back(type_value.get()); objects_.push_back(std::move(type_value)); @@ -2652,6 +2692,8 @@ SharedComponentValidator::TypeBaseVector* SharedComponentValidator::GetSort( return &component->core_funcs; case ComponentSort::CoreMemory: return &component->core_memories; + case ComponentSort::CoreInstance: + return &component->core_instances; case ComponentSort::CoreModule: return &component->core_modules; case ComponentSort::Func: @@ -2670,14 +2712,33 @@ Result SharedComponentValidator::CheckIndex(const Location& loc, CheckMode mode, TypeBase** out_type) { std::vector* sort_vector = GetSort(current_, sort); - if (sort_vector == nullptr) { - return Result::Ok; - } + Index max; - Index max = static_cast(sort_vector->size()); - if (mode == ExcludeLast) { - assert(max > 0); - max--; + if (sort_vector == nullptr) { + assert(mode == IncludeLast); + Component* component = CurrentAsComponent(); + switch (sort) { + case ComponentSort::CoreTable: + max = component->core_tables; + break; + case ComponentSort::CoreGlobal: + max = component->core_globals; + break; + case ComponentSort::CoreTag: + max = component->core_tags; + break; + case ComponentSort::CoreType: + max = component->core_types; + break; + default: + return Result::Ok; + } + } else { + max = static_cast(sort_vector->size()); + if (mode == ExcludeLast) { + assert(max > 0); + max--; + } } if (index >= max) { @@ -2838,7 +2899,7 @@ Result SharedComponentValidator::CheckExternalInfo( ComponentSort sort = external_info.sort; if (sort == ComponentSort::Type && external_info.external == ComponentExternalDesc::TypeSubRes) { - auto type_value = MakeUnique(TypeDef::Resource); + auto type_value = MakeUnique(TypeResource::Imported); *out_type_base = type_value.get(); objects_.push_back(std::move(type_value)); return Result::Ok; diff --git a/third_party/wabt/src/stream.cc b/third_party/wabt/src/stream.cc index c808d2ce7..4847d04a3 100644 --- a/third_party/wabt/src/stream.cc +++ b/third_party/wabt/src/stream.cc @@ -23,9 +23,8 @@ #define DUMP_OCTETS_PER_LINE 16 #define DUMP_OCTETS_PER_GROUP 2 -#define ERROR0(msg) fprintf(stderr, "%s:%d: " msg, __FILE__, __LINE__) -#define ERROR(fmt, ...) \ - fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) +#define UNIMPLMENTED(msg) fprintf(stderr, "%s:%d: " msg, __FILE__, __LINE__) +#define ERROR(fmt, ...) fprintf(stderr, "wabt: " fmt, __VA_ARGS__) namespace wabt { @@ -136,7 +135,8 @@ Result OutputBuffer::WriteToFile(nonstd::string_view filename) const { std::string filename_str(filename); FILE* file = fopen(filename_str.c_str(), "wb"); if (!file) { - ERROR("unable to open %s for writing\n", filename_str.c_str()); + ERROR("unable to open %s for writing: %s\n", filename_str.c_str(), + strerror(errno)); return Result::Error; } @@ -238,7 +238,8 @@ FileStream::FileStream(nonstd::string_view filename, Stream* log_stream) if (file_) { should_close_ = true; } else { - ERROR("fopen name=\"%s\" failed, errno=%d\n", filename_str.c_str(), errno); + ERROR("unable to open %s for writing: %s\n", filename_str.c_str(), + strerror(errno)); } } @@ -304,7 +305,7 @@ Result FileStream::MoveDataImpl(size_t dst_offset, return Result::Ok; } // TODO(binji): implement if needed. - ERROR0("FileStream::MoveDataImpl not implemented!\n"); + UNIMPLMENTED("FileStream::MoveDataImpl not implemented!\n"); return Result::Error; } @@ -313,7 +314,7 @@ Result FileStream::TruncateImpl(size_t size) { return Result::Error; } // TODO(binji): implement if needed. - ERROR0("FileStream::TruncateImpl not implemented!\n"); + UNIMPLMENTED("FileStream::TruncateImpl not implemented!\n"); return Result::Error; } diff --git a/third_party/wabt/src/type-checker.cc b/third_party/wabt/src/type-checker.cc index b613aa0c1..7e6fb2455 100644 --- a/third_party/wabt/src/type-checker.cc +++ b/third_party/wabt/src/type-checker.cc @@ -939,19 +939,15 @@ Result TypeChecker::OnArrayNewFixed(Type ref_type, Result result = Result::Ok; array_type = ToUnpackedType(array_type); for (Index i = 0; i < count; ++i) { - result |= PeekAndCheckType(count - i - 1, array_type); - } - - if (Failed(result)) { - // To improve performance, type vector - // conversion is only done on error. - TypeVector types; - types.reserve(count); - - for (size_t i = 0; i < count; ++i) { - types.push_back(array_type); + // For a very large count, PrintStackIfFailedV might print too many values. + if (Failed(PeekAndCheckType(count - i - 1, array_type))) { + Type actual = Type::Any; + PeekType(count - i - 1, &actual); + PrintError("array.new_fixed expects %s but got %s at depth %" PRIindex, + array_type.GetName().c_str(), actual.GetName().c_str(), i); + result = Result::Error; + break; } - PrintStackIfFailedV(result, "array.new_fixed", types, /*is_end=*/false); } result |= DropTypes(count); @@ -1160,8 +1156,10 @@ Result TypeChecker::OnReturnCall(const TypeVector& param_types, } Result TypeChecker::OnReturnCallIndirect(const TypeVector& param_types, - const TypeVector& result_types) { - Result result = PopAndCheck1Type(Type::I32, "return_call_indirect"); + const TypeVector& result_types, + const Limits& table_limits) { + Result result = PopAndCheck1Type(table_limits.is_64 ? Type::I64 : Type::I32, + "return_call_indirect"); result |= PopAndCheckSignature(param_types, "return_call_indirect"); result |= PopAndCheckReturnCall(result_types, "return_call_indirect"); diff --git a/third_party/wabt/src/walrus/binary-reader-walrus.cc b/third_party/wabt/src/walrus/binary-reader-walrus.cc index 70d7199f3..aad77290e 100644 --- a/third_party/wabt/src/walrus/binary-reader-walrus.cc +++ b/third_party/wabt/src/walrus/binary-reader-walrus.cc @@ -1629,8 +1629,8 @@ std::string ReadWasmBinary(const std::string &filename, const uint8_t *data, siz class ComponentBinaryReaderDelegateWalrus: public ComponentBinaryReaderDelegate { public: - ComponentBinaryReaderDelegateWalrus(WASMComponentBinaryReaderDelegate *delegate, const std::string &filename, const uint32_t featureFlags) : - m_externalDelegate(delegate), m_validator(&m_errors, filename, ValidateOptions(getFeatures(featureFlags))) { + ComponentBinaryReaderDelegateWalrus(WASMComponentBinaryReaderDelegate *delegate) : + m_externalDelegate(delegate), m_validator(&m_errors, delegate->filename(), ValidateOptions(getFeatures(delegate->featureFlags()))) { } Location GetLocation() const { @@ -1644,12 +1644,16 @@ class ComponentBinaryReaderDelegateWalrus: public ComponentBinaryReaderDelegate return true; } + Result CheckParseError() { + return m_externalDelegate->WalrusParseError().empty() ? Result::Ok : Result::Error; + } + Result OnCoreModule(const void* data, size_t size, const ReadBinaryOptions& options) override { CHECK_RESULT(m_validator.OnCoreModule()); m_externalDelegate->OnCoreModule(data, size, options); - return Result::Ok; + return CheckParseError(); } Result BeginComponent(uint32_t version, size_t depth) override { @@ -1780,7 +1784,7 @@ class ComponentBinaryReaderDelegateWalrus: public ComponentBinaryReaderDelegate const ComponentStringLoc& name) override { CHECK_RESULT(m_validator.OnAliasCoreExport(GetLocation(), sort, core_instance_index, name)); m_externalDelegate->OnAliasCoreExport(sort, core_instance_index.index, name); - return Result::Ok; + return CheckParseError(); } Result OnAliasOuter(ComponentSort sort, @@ -2076,12 +2080,12 @@ class ComponentBinaryReaderDelegateWalrus: public ComponentBinaryReaderDelegate SharedComponentValidator m_validator; }; -std::string ReadWasmComponentBinary(const std::string &filename, const uint8_t *data, size_t size, WASMComponentBinaryReaderDelegate *delegate, const uint32_t featureFlags) { +std::string ReadWasmComponentBinary(const uint8_t *data, size_t size, WASMComponentBinaryReaderDelegate *delegate) { const bool kReadDebugNames = false; const bool kStopOnFirstError = true; const bool kFailOnCustomSectionError = true; - ReadBinaryOptions options(getFeatures(featureFlags), nullptr, kReadDebugNames, kStopOnFirstError, kFailOnCustomSectionError); - ComponentBinaryReaderDelegateWalrus binaryReaderDelegateWalrus(delegate, filename, featureFlags); + ReadBinaryOptions options(getFeatures(delegate->featureFlags()), nullptr, kReadDebugNames, kStopOnFirstError, kFailOnCustomSectionError); + ComponentBinaryReaderDelegateWalrus binaryReaderDelegateWalrus(delegate); Result result = ReadBinaryComponent(data, size, &binaryReaderDelegateWalrus, options); if (WABT_UNLIKELY(binaryReaderDelegateWalrus.m_errors.size())) { diff --git a/third_party/wabt/src/wast-parser.cc b/third_party/wabt/src/wast-parser.cc index 16b2fb4f1..a43b12753 100644 --- a/third_party/wabt/src/wast-parser.cc +++ b/third_party/wabt/src/wast-parser.cc @@ -4097,6 +4097,9 @@ Result WastParser::ParseComponentCoreSort(ComponentSort* out_sort) { case TokenType::Global: *out_sort = ComponentSort::CoreGlobal; break; + case TokenType::Tag: + *out_sort = ComponentSort::CoreTag; + break; case TokenType::Type: *out_sort = ComponentSort::CoreType; break;