Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions include/wabt/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,20 @@ class BinaryReaderLogging : public BinaryReaderDelegate {

Result BeginTypeSection(Offset size) override;
Result OnTypeCount(Index count) override;
Result OnRecursiveGroup(Index first_type_index, Index type_count) override;
Result OnFuncType(Index index,
Index param_count,
Type* param_types,
Index result_count,
Type* result_types) override;
Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
Result OnArrayType(Index index, TypeMut field) override;
Type* result_types,
SupertypesInfo* supertypes) override;
Result OnStructType(Index index,
Index field_count,
TypeMut* fields,
SupertypesInfo* supertypes) override;
Result OnArrayType(Index index,
TypeMut field,
SupertypesInfo* supertypes) override;
Result EndTypeSection() override;

Result BeginImportSection(Offset size) override;
Expand Down Expand Up @@ -435,6 +442,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
void LogType(Type type);
void LogTypes(Index type_count, Type* types);
void LogTypes(TypeVector& types);
void LogSupertypesInfo(SupertypesInfo* supertypes);
void LogField(TypeMut field);

Stream* stream_;
Expand Down
15 changes: 12 additions & 3 deletions include/wabt/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,29 @@ class BinaryReaderNop : public BinaryReaderDelegate {

/* Type section */
Result BeginTypeSection(Offset size) override { return Result::Ok; }
Result OnRecursiveGroup(Index first_type_index, Index type_count) override {
return Result::Ok;
}
Result OnTypeCount(Index count) override { return Result::Ok; }
Result OnFuncType(Index index,
Index param_count,
Type* param_types,
Index result_count,
Type* result_types) override {
Type* result_types,
SupertypesInfo* supertypes) override {
return Result::Ok;
}
Result OnStructType(Index index,
Index field_count,
TypeMut* fields) override {
TypeMut* fields,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should be using C++ std::array rather then size + ptr in these API ? But I see its a pre-existing thing so no worries for this PR.

SupertypesInfo* supertypes) override {
return Result::Ok;
}
Result OnArrayType(Index index,
TypeMut field,
SupertypesInfo* supertypes) override {
return Result::Ok;
}
Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; }
Result EndTypeSection() override { return Result::Ok; }

/* Import section */
Expand Down
20 changes: 16 additions & 4 deletions include/wabt/binary-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,20 @@ struct ReadBinaryOptions {
bool skip_function_bodies = false;
};

// TODO: Move somewhere else?
// TODO: Move both TypeMut and SupertypesInfo somewhere else?
struct TypeMut {
Type type;
bool mutable_;
};
using TypeMutVector = std::vector<TypeMut>;

// Type extension introduced by the Garbage Collector proposal
struct SupertypesInfo {
bool is_final_sub_type;
Index sub_type_count;
Index* sub_types;
};

struct CatchClause {
CatchKind kind;
Index tag;
Expand Down Expand Up @@ -104,15 +111,20 @@ class BinaryReaderDelegate {
/* Type section */
virtual Result BeginTypeSection(Offset size) = 0;
virtual Result OnTypeCount(Index count) = 0;
virtual Result OnRecursiveGroup(Index first_type_index, Index type_count) = 0;
virtual Result OnFuncType(Index index,
Index param_count,
Type* param_types,
Index result_count,
Type* result_types) = 0;
Type* result_types,
SupertypesInfo* supertypes) = 0;
virtual Result OnStructType(Index index,
Index field_count,
TypeMut* fields) = 0;
virtual Result OnArrayType(Index index, TypeMut field) = 0;
TypeMut* fields,
SupertypesInfo* supertypes) = 0;
virtual Result OnArrayType(Index index,
TypeMut field,
SupertypesInfo* supertypes) = 0;
virtual Result EndTypeSection() = 0;

/* Import section */
Expand Down
14 changes: 14 additions & 0 deletions include/wabt/interp/interp-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ inline bool FuncType::classof(const ExternType* type) {
inline FuncType::FuncType(ValueTypes params, ValueTypes results)
: ExternType(ExternKind::Func), params(params), results(results), func_types(nullptr) {}

inline FuncType::FuncType(TypeKind kind, ValueTypes params, ValueTypes results)
: ExternType(ExternKind::Func),
kind(kind),
canonical_index(kInvalidIndex),
canonical_sub_index(kInvalidIndex),
is_final_sub_type(true),
recursive_start(0),
recursive_count(0),
params(params),
results(results),
func_types(nullptr) {
assert((kind == TypeKind::Struct || kind == TypeKind::Array) && params.size() == results.size());
}

//// TableType ////
// static
inline bool TableType::classof(const ExternType* type) {
Expand Down
23 changes: 23 additions & 0 deletions include/wabt/interp/interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,14 +178,37 @@ struct FuncType : ExternType {
static const ExternKind skind = ExternKind::Func;
static bool classof(const ExternType* type);

enum class TypeKind {
Func,
Struct,
Array,
};

// Currently FuncType also represents Struct and Array types.
// In the latter case, the mutability is stored in results array,
// which must have the same size as params.
// TODO: support separate types for Structs and Arrays or rename FuncType.
static const Type::Enum Mutable = Type::I32;
static const Type::Enum Immutable = Type::I64;

explicit FuncType(ValueTypes params, ValueTypes results);
explicit FuncType(TypeKind kind, ValueTypes params, ValueTypes results);

std::unique_ptr<ExternType> Clone() const override;

friend Result Match(const FuncType& expected,
const FuncType& actual,
std::string* out_msg);

TypeKind kind = FuncType::TypeKind::Func;
// These two are needed for fast dynamic type comparison.
Index canonical_index = kInvalidIndex;
Index canonical_sub_index = kInvalidIndex;
// These three are needed for type equality comparisons
// across different modules (import/export validation).
bool is_final_sub_type = true;
Index recursive_start = 0;
Index recursive_count = 0;
ValueTypes params;
ValueTypes results;
// When params or results contain references, the referenced
Expand Down
41 changes: 34 additions & 7 deletions include/wabt/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,19 @@ enum class TypeEntryKind {
Array,
};

struct TypeEntrySupertypesInfo {
TypeEntrySupertypesInfo(bool is_final_sub_type)
: is_final_sub_type(is_final_sub_type) {}

void InitSubTypes(Index* sub_type_list, Index sub_type_count);

bool is_final_sub_type;
// The binary/text format allows any number of subtypes.
// Currently, validator rejects lists which size is greater
// than 1, but this might be changed in the future.
VarVector sub_types;
};

class TypeEntry {
public:
WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry);
Expand All @@ -307,12 +320,17 @@ class TypeEntry {

Location loc;
std::string name;
TypeEntrySupertypesInfo supertypes;

protected:
explicit TypeEntry(TypeEntryKind kind,
bool is_final_sub_type,
std::string_view name = std::string_view(),
const Location& loc = Location())
: loc(loc), name(name), kind_(kind) {}
: loc(loc),
name(name),
supertypes(is_final_sub_type),
kind_(kind) {}

TypeEntryKind kind_;
};
Expand All @@ -323,8 +341,8 @@ class FuncType : public TypeEntry {
return entry->kind() == TypeEntryKind::Func;
}

explicit FuncType(std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Func, name) {}
explicit FuncType(bool is_final_sub_type, std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Func, is_final_sub_type, name) {}

Index GetNumParams() const { return sig.GetNumParams(); }
Index GetNumResults() const { return sig.GetNumResults(); }
Expand Down Expand Up @@ -353,8 +371,8 @@ class StructType : public TypeEntry {
return entry->kind() == TypeEntryKind::Struct;
}

explicit StructType(std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Struct) {}
explicit StructType(bool is_final_sub_type, std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Struct, is_final_sub_type, name) {}

std::vector<Field> fields;
};
Expand All @@ -365,12 +383,19 @@ class ArrayType : public TypeEntry {
return entry->kind() == TypeEntryKind::Array;
}

explicit ArrayType(std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Array) {}
explicit ArrayType(bool is_final_sub_type, std::string_view name = std::string_view())
: TypeEntry(TypeEntryKind::Array, is_final_sub_type, name) {}

Field field;
};

struct RecGroupRange {
Index first_type_index;
Index type_count;

Index EndTypeIndex() const { return first_type_index + type_count; }
};

struct FuncDeclaration {
Index GetNumParams() const { return sig.GetNumParams(); }
Index GetNumResults() const { return sig.GetNumResults(); }
Expand Down Expand Up @@ -1322,6 +1347,8 @@ struct Module {
std::vector<Import*> imports;
std::vector<Export*> exports;
std::vector<TypeEntry*> types;
// Ordered list of recursive group type ranges.
std::vector<RecGroupRange> rec_group_ranges;
std::vector<Table*> tables;
std::vector<ElemSegment*> elem_segments;
std::vector<Memory*> memories;
Expand Down
54 changes: 30 additions & 24 deletions include/wabt/shared-validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
#include "wabt/opcode.h"
#include "wabt/type-checker.h"

#include "wabt/binary-reader.h" // For TypeMut.

namespace wabt {

struct ValidateOptions {
Expand All @@ -48,7 +46,11 @@ enum class TableImportStatus {
class SharedValidator {
public:
WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator);
using TypeEntry = TypeChecker::TypeEntry;
using FuncType = TypeChecker::FuncType;
using StructType = TypeChecker::StructType;
using ArrayType = TypeChecker::ArrayType;
using RecGroup = TypeChecker::RecGroup;
SharedValidator(Errors*,
std::string_view filename,
const ValidateOptions& options);
Expand All @@ -70,16 +72,28 @@ class SharedValidator {

Index GetLocalCount() const;

// The canonical index is the lowest index, which represents
// the same type as the type_index. The canonical index is
// always less or equal than type_index.
Index GetCanonicalTypeIndex(Index type_index);

Result EndModule();

Result OnRecursiveGroup(Index first_type_index, Index type_count);
Result OnFuncType(const Location&,
Index param_count,
const Type* param_types,
Index result_count,
const Type* result_types,
Index type_index);
Result OnStructType(const Location&, Index field_count, TypeMut* fields);
Result OnArrayType(const Location&, TypeMut field);
Index type_index,
SupertypesInfo* supertypes);
Result OnStructType(const Location&,
Index field_count,
TypeMut* fields,
SupertypesInfo* supertypes);
Result OnArrayType(const Location&,
TypeMut field,
SupertypesInfo* supertypes);

Result OnFunction(const Location&, Var sig_var);
Result OnTable(const Location&, Type elem_type, const Limits&, TableImportStatus import_status, TableInitExprStatus init_provided);
Expand Down Expand Up @@ -233,20 +247,6 @@ class SharedValidator {
Result OnUnreachable(const Location&);

private:
struct StructType {
StructType() = default;
StructType(const TypeMutVector& fields) : fields(fields) {}

TypeMutVector fields;
};

struct ArrayType {
ArrayType() = default;
ArrayType(TypeMut field) : field(field) {}

TypeMut field;
};

struct TableType {
TableType() = default;
TableType(Type element, Limits limits) : element(element), limits(limits) {}
Expand Down Expand Up @@ -302,7 +302,11 @@ class SharedValidator {
Type actual,
Type expected,
const char* desc);
Result CheckReferenceType(const Location&, Type type, const char* desc);
Result CheckReferenceType(const Location&,
Type type,
Index end_index,
const char* desc);
Result CheckSupertypes(const Location&, SupertypesInfo* supertypes);
Result CheckLimits(const Location&,
const Limits&,
uint64_t absolute_max,
Expand Down Expand Up @@ -347,6 +351,8 @@ class SharedValidator {
void RestoreLocalRefs(Result result);
void IgnoreLocalRefs();

Index GetRecGroupEnd();

ValidateOptions options_;
Errors* errors_;
std::string_view filename_;
Expand All @@ -355,10 +361,7 @@ class SharedValidator {
Location expr_loc_ = Location(kInvalidOffset);
bool in_init_expr_ = false;

Index num_types_ = 0;
std::map<Index, FuncType> func_types_;
std::map<Index, StructType> struct_types_;
std::map<Index, ArrayType> array_types_;
TypeChecker::TypeFields type_fields_;

std::vector<FuncType> funcs_; // Includes imported and defined.
std::vector<TableType> tables_; // Includes imported and defined.
Expand All @@ -369,6 +372,9 @@ class SharedValidator {
Index starts_ = 0;
Index num_imported_globals_ = 0;
Index data_segments_ = 0;
Index last_rec_type_end_ = 0;
// Recursive type checks may enter to infinite loop for invalid values.
Result type_validation_result_ = Result::Ok;

// Includes parameters, since this is only used for validating
// local.{get,set,tee} instructions.
Expand Down
Loading
Loading