diff --git a/include/wasp/text/resolve_context.h b/include/wasp/text/resolve_context.h index 364efafb..e3a479ed 100644 --- a/include/wasp/text/resolve_context.h +++ b/include/wasp/text/resolve_context.h @@ -49,10 +49,11 @@ using DefinedTypeList = std::vector; // `deferred_list_` set below. class FunctionTypeMap { public: - using List = std::vector; + using List = std::vector>; void BeginModule(); void Define(BoundFunctionType); + void SkipIndex(); Index Use(FunctionType); Index Use(BoundFunctionType); // Returns the deferred defined types. diff --git a/src/text/resolve.cc b/src/text/resolve.cc index fb7b5e5f..148e459c 100644 --- a/src/text/resolve.cc +++ b/src/text/resolve.cc @@ -92,6 +92,8 @@ void Define(ResolveContext& context, const DefinedType& defined_type) { BoundFunctionType bft = defined_type.function_type(); Resolve(context, bft); context.function_type_map.Define(bft); + } else { + context.function_type_map.SkipIndex(); } } diff --git a/src/text/resolve_context.cc b/src/text/resolve_context.cc index 630b0b43..786884b7 100644 --- a/src/text/resolve_context.cc +++ b/src/text/resolve_context.cc @@ -91,6 +91,10 @@ void FunctionTypeMap::Define(BoundFunctionType bound_type) { list_.push_back(ToFunctionType(bound_type)); } +void FunctionTypeMap::SkipIndex() { + list_.push_back(nullopt); +} + Index FunctionTypeMap::Use(FunctionType type) { auto iter = FindIter(list_, type); if (iter != list_.end()) { @@ -113,8 +117,9 @@ Index FunctionTypeMap::Use(BoundFunctionType type) { auto FunctionTypeMap::EndModule() -> DefinedTypeList { DefinedTypeList defined_types; for (auto&& deferred : deferred_list_) { - list_.push_back(deferred); - defined_types.push_back(ToDefinedType(deferred)); + assert(deferred.has_value()); + list_.push_back(*deferred); + defined_types.push_back(ToDefinedType(*deferred)); } deferred_list_.clear(); return defined_types; @@ -151,7 +156,9 @@ FunctionTypeMap::List::const_iterator FunctionTypeMap::FindIter( const List& list, const FunctionType& type) { return std::find_if(list.begin(), list.end(), - [&](const FunctionType& ft) { return IsSame(type, ft); }); + [&](const optional& ft) { + return ft && IsSame(type, *ft); + }); } // static diff --git a/src/tools/wat2wasm.cc b/src/tools/wat2wasm.cc index 746e2778..419beb22 100644 --- a/src/tools/wat2wasm.cc +++ b/src/tools/wat2wasm.cc @@ -45,6 +45,9 @@ #include "wasp/valid/context.h" #include "wasp/valid/validate.h" +#include "wasp/text/formatters.h" +#include "wasp/text/write.h" + namespace fs = std::filesystem; namespace wasp { diff --git a/src/valid/validate.cc b/src/valid/validate.cc index e642ac9b..4d921931 100644 --- a/src/valid/validate.cc +++ b/src/valid/validate.cc @@ -54,7 +54,12 @@ bool BeginCode(Context& context, Location loc) { // Don't validate the index, should have already been validated at this point. if (function.type_index < context.defined_type_count) { const auto& defined_type = context.types[function.type_index]; - // TODO: Add support for struct and array types. + if (!defined_type.is_function_type()) { + context.errors->OnError(loc, + concat("Function must have a function type.")); + return false; + } + assert(defined_type.is_function_type()); const auto& function_type = defined_type.function_type(); context.locals.Append(function_type->param_types); diff --git a/test/text/resolve_test.cc b/test/text/resolve_test.cc index 0a7ee3ae..1ca45382 100644 --- a/test/text/resolve_test.cc +++ b/test/text/resolve_test.cc @@ -1633,3 +1633,39 @@ TEST_F(TextResolveTest, ModuleWithDeferredTypes) { {}}}, }); } + +TEST_F(TextResolveTest, ModuleWithDeferredTypes_AndStruct) { + OK( + Module{ + // (type (struct)) + ModuleItem{DefinedType{nullopt, StructType{}}}, + // (func (type 1) (param i32)) + ModuleItem{Function{FunctionDesc{ + nullopt, + Var{Index{1}}, + BoundFunctionType{{BVT{nullopt, VT_I32}}, {}}, + }, + {}, + {}, + {}}}, + + // The deferred defined types. + // (type (func (param i32)) + ModuleItem{DefinedType{ + nullopt, + BoundFunctionType{BoundValueTypeList{BVT{nullopt, VT_I32}}, {}}}}, + }, + Module{ + // (type (struct)) + ModuleItem{DefinedType{nullopt, StructType{}}}, + // (func (param i32)) + ModuleItem{Function{FunctionDesc{ + nullopt, + nullopt, + BoundFunctionType{{BVT{nullopt, VT_I32}}, {}}, + }, + {}, + {}, + {}}}, + }); +} diff --git a/test/valid/validate_code_test.cc b/test/valid/validate_code_test.cc index 4fc81ce7..5c0c4eec 100644 --- a/test/valid/validate_code_test.cc +++ b/test/valid/validate_code_test.cc @@ -53,6 +53,15 @@ TEST(ValidateCodeTest, BeginCode_TypeIndexOOB) { EXPECT_FALSE(BeginCode(context, Location{})); } +TEST(ValidateCodeTest, BeginCode_NonFunctionType) { + TestErrors errors; + Context context{errors}; + context.types.push_back(DefinedType{StructType{}}); + context.defined_type_count = 1; + context.functions.push_back(Function{0}); + EXPECT_FALSE(BeginCode(context, Location{})); +} + TEST(ValidateCodeTest, Locals) { TestErrors errors; Context context{errors};