| /* |
| * Copyright 2020 WebAssembly Community Group participants |
| * |
| * 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. |
| */ |
| |
| #ifndef WABT_SHARED_VALIDATOR_H_ |
| #define WABT_SHARED_VALIDATOR_H_ |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "wabt/common.h" |
| #include "wabt/error.h" |
| #include "wabt/feature.h" |
| #include "wabt/ir.h" |
| #include "wabt/opcode.h" |
| #include "wabt/type-checker.h" |
| |
| #include "wabt/binary-reader.h" // For TypeMut. |
| |
| namespace wabt { |
| |
| struct ValidateOptions { |
| ValidateOptions() = default; |
| ValidateOptions(const Features& features) : features(features) {} |
| |
| Features features; |
| }; |
| |
| class SharedValidator { |
| public: |
| WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator); |
| SharedValidator(Errors*, const ValidateOptions& options); |
| |
| // TODO: Move into SharedValidator? |
| using Label = TypeChecker::Label; |
| size_t type_stack_size() const { return typechecker_.type_stack_size(); } |
| Result GetLabel(Index depth, Label** out_label) { |
| return typechecker_.GetLabel(depth, out_label); |
| } |
| Result GetCatchCount(Index depth, Index* out_count) { |
| return typechecker_.GetCatchCount(depth, out_count); |
| } |
| |
| Result WABT_PRINTF_FORMAT(3, 4) |
| PrintError(const Location& loc, const char* fmt, ...); |
| |
| void OnTypecheckerError(const char* msg); |
| |
| Index GetLocalCount() const; |
| |
| Result EndModule(); |
| |
| 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); |
| |
| Result OnFunction(const Location&, Var sig_var); |
| Result OnTable(const Location&, Type elem_type, const Limits&); |
| Result OnMemory(const Location&, const Limits&); |
| Result OnGlobalImport(const Location&, Type type, bool mutable_); |
| Result OnGlobal(const Location&, Type type, bool mutable_); |
| Result OnTag(const Location&, Var sig_var); |
| |
| Result OnExport(const Location&, |
| ExternalKind, |
| Var item_var, |
| std::string_view name); |
| |
| Result OnStart(const Location&, Var func_var); |
| |
| Result OnElemSegment(const Location&, Var table_var, SegmentKind); |
| Result OnElemSegmentElemType(const Location&, Type elem_type); |
| |
| void OnDataCount(Index count); |
| Result OnDataSegment(const Location&, Var memory_var, SegmentKind); |
| |
| Result BeginInitExpr(const Location&, Type type); |
| Result EndInitExpr(); |
| |
| Result BeginFunctionBody(const Location&, Index func_index); |
| Result EndFunctionBody(const Location&); |
| Result OnLocalDecl(const Location&, Index count, Type type); |
| |
| Result OnAtomicFence(const Location&, uint32_t consistency_model); |
| Result OnAtomicLoad(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnAtomicNotify(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnAtomicRmwCmpxchg(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnAtomicRmw(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnAtomicStore(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnAtomicWait(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnBinary(const Location&, Opcode); |
| Result OnBlock(const Location&, Type sig_type); |
| Result OnBr(const Location&, Var depth); |
| Result OnBrIf(const Location&, Var depth); |
| Result BeginBrTable(const Location&); |
| Result OnBrTableTarget(const Location&, Var depth); |
| Result EndBrTable(const Location&); |
| Result OnCall(const Location&, Var func_var); |
| Result OnCallIndirect(const Location&, Var sig_var, Var table_var); |
| Result OnCallRef(const Location&, Index* function_type_index); |
| Result OnCatch(const Location&, Var tag_var, bool is_catch_all); |
| Result OnCompare(const Location&, Opcode); |
| Result OnConst(const Location&, Type); |
| Result OnConvert(const Location&, Opcode); |
| Result OnDataDrop(const Location&, Var segment_var); |
| Result OnDelegate(const Location&, Var depth); |
| Result OnDrop(const Location&); |
| Result OnElemDrop(const Location&, Var segment_var); |
| Result OnElse(const Location&); |
| Result OnEnd(const Location&); |
| Result OnGlobalGet(const Location&, Var); |
| Result OnGlobalSet(const Location&, Var); |
| Result OnIf(const Location&, Type sig_type); |
| Result OnLoad(const Location&, Opcode, Var memidx, Address align, Address offset); |
| Result OnLoadSplat(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnLoadZero(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnLocalGet(const Location&, Var); |
| Result OnLocalSet(const Location&, Var); |
| Result OnLocalTee(const Location&, Var); |
| Result OnLoop(const Location&, Type sig_type); |
| Result OnMemoryCopy(const Location&, Var destmemidx, Var srcmemidx); |
| Result OnMemoryFill(const Location&, Var memidx); |
| Result OnMemoryGrow(const Location&, Var memidx); |
| Result OnMemoryInit(const Location&, Var segment_var, Var memidx); |
| Result OnMemorySize(const Location&, Var memidx); |
| Result OnNop(const Location&); |
| Result OnRefFunc(const Location&, Var func_var); |
| Result OnRefIsNull(const Location&); |
| Result OnRefNull(const Location&, Type type); |
| Result OnRethrow(const Location&, Var depth); |
| Result OnReturnCall(const Location&, Var func_var); |
| Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var); |
| Result OnReturn(const Location&); |
| Result OnSelect(const Location&, Index result_count, Type* result_types); |
| Result OnSimdLaneOp(const Location&, Opcode, uint64_t lane_idx); |
| Result OnSimdLoadLane(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset, |
| uint64_t lane_idx); |
| Result OnSimdStoreLane(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset, |
| uint64_t lane_idx); |
| Result OnSimdShuffleOp(const Location&, Opcode, v128 lane_idx); |
| Result OnStore(const Location&, |
| Opcode, |
| Var memidx, |
| Address align, |
| Address offset); |
| Result OnTableCopy(const Location&, Var dst_var, Var src_var); |
| Result OnTableFill(const Location&, Var table_var); |
| Result OnTableGet(const Location&, Var table_var); |
| Result OnTableGrow(const Location&, Var table_var); |
| Result OnTableInit(const Location&, Var segment_var, Var table_var); |
| Result OnTableSet(const Location&, Var table_var); |
| Result OnTableSize(const Location&, Var table_var); |
| Result OnTernary(const Location&, Opcode); |
| Result OnThrow(const Location&, Var tag_var); |
| Result OnTry(const Location&, Type sig_type); |
| Result OnUnary(const Location&, Opcode); |
| Result OnUnreachable(const Location&); |
| |
| private: |
| struct FuncType { |
| FuncType() = default; |
| FuncType(const TypeVector& params, |
| const TypeVector& results, |
| Index type_index) |
| : params(params), results(results), type_index(type_index) {} |
| |
| TypeVector params; |
| TypeVector results; |
| Index type_index; |
| }; |
| |
| 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) {} |
| |
| Type element = Type::Any; |
| Limits limits; |
| }; |
| |
| struct MemoryType { |
| MemoryType() = default; |
| MemoryType(Limits limits) : limits(limits) {} |
| |
| Limits limits; |
| }; |
| |
| struct GlobalType { |
| GlobalType() = default; |
| GlobalType(Type type, bool mutable_) : type(type), mutable_(mutable_) {} |
| |
| Type type = Type::Any; |
| bool mutable_ = true; |
| }; |
| |
| struct TagType { |
| TypeVector params; |
| }; |
| |
| struct ElemType { |
| ElemType() = default; |
| ElemType(Type element, bool is_active, Type table_type) |
| : element(element), is_active(is_active), table_type(table_type) {} |
| |
| Type element; |
| bool is_active; |
| Type table_type; |
| }; |
| |
| struct LocalDecl { |
| Type type; |
| Index end; |
| }; |
| |
| bool ValidInitOpcode(Opcode opcode) const; |
| Result CheckInstr(Opcode opcode, const Location& loc); |
| Result CheckType(const Location&, |
| Type actual, |
| Type expected, |
| const char* desc); |
| Result CheckLimits(const Location&, |
| const Limits&, |
| uint64_t absolute_max, |
| const char* desc); |
| |
| Result CheckLocalIndex(Var local_var, Type* out_type); |
| |
| Result CheckDeclaredFunc(Var func_var); |
| |
| Result CheckIndex(Var var, Index max_index, const char* desc); |
| template <typename T> |
| Result CheckIndexWithValue(Var var, |
| const std::vector<T>& values, |
| T* out, |
| const char* desc); |
| Result CheckFuncTypeIndex(Var sig_var, FuncType* out = nullptr); |
| Result CheckFuncIndex(Var func_var, FuncType* out = nullptr); |
| Result CheckTableIndex(Var table_var, TableType* out = nullptr); |
| Result CheckMemoryIndex(Var memory_var, MemoryType* out = nullptr); |
| Result CheckGlobalIndex(Var global_var, GlobalType* out = nullptr); |
| Result CheckTagIndex(Var tag_var, TagType* out = nullptr); |
| Result CheckElemSegmentIndex(Var elem_segment_var, ElemType* out = nullptr); |
| Result CheckDataSegmentIndex(Var data_segment_var); |
| |
| Result CheckAlign(const Location&, Address align, Address natural_align); |
| Result CheckOffset(const Location&, Address offset, const Limits& limits); |
| Result CheckAtomicAlign(const Location&, |
| Address align, |
| Address natural_align); |
| |
| Result CheckBlockSignature(const Location&, |
| Opcode, |
| Type sig_type, |
| TypeVector* out_param_types, |
| TypeVector* out_result_types); |
| |
| Index GetFunctionTypeIndex(Index func_index) const; |
| |
| TypeVector ToTypeVector(Index count, const Type* types); |
| |
| ValidateOptions options_; |
| Errors* errors_; |
| TypeChecker typechecker_; // TODO: Move into SharedValidator. |
| // Cached for access by OnTypecheckerError. |
| 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_; |
| |
| std::vector<FuncType> funcs_; // Includes imported and defined. |
| std::vector<TableType> tables_; // Includes imported and defined. |
| std::vector<MemoryType> memories_; // Includes imported and defined. |
| std::vector<GlobalType> globals_; // Includes imported and defined. |
| std::vector<TagType> tags_; // Includes imported and defined. |
| std::vector<ElemType> elems_; |
| Index starts_ = 0; |
| Index num_imported_globals_ = 0; |
| Index data_segments_ = 0; |
| |
| // Includes parameters, since this is only used for validating |
| // local.{get,set,tee} instructions. |
| std::vector<LocalDecl> locals_; |
| |
| std::set<std::string> export_names_; // Used to check for duplicates. |
| std::set<Index> declared_funcs_; // TODO: optimize? |
| std::vector<Var> check_declared_funcs_; |
| }; |
| |
| } // namespace wabt |
| |
| #endif // WABT_SHARED_VALIDATOR_H_ |