/* * Copyright 2016 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. */ #include "binary-reader-interpreter.h" #include #include #include #include #include #include "binary-reader-nop.h" #include "interpreter.h" #include "type-checker.h" #include "writer.h" #define CHECK_RESULT(expr) \ do { \ if (WABT_FAILED(expr)) \ return Result::Error; \ } while (0) namespace wabt { namespace { typedef std::vector Uint32Vector; typedef std::vector Uint32VectorVector; struct Label { Label(uint32_t offset, uint32_t fixup_offset); uint32_t offset; /* branch location in the istream */ uint32_t fixup_offset; }; Label::Label(uint32_t offset, uint32_t fixup_offset) : offset(offset), fixup_offset(fixup_offset) {} struct ElemSegmentInfo { ElemSegmentInfo(uint32_t* dst, uint32_t func_index) : dst(dst), func_index(func_index) {} uint32_t* dst; uint32_t func_index; }; struct DataSegmentInfo { DataSegmentInfo(void* dst_data, const void* src_data, uint32_t size) : dst_data(dst_data), src_data(src_data), size(size) {} void* dst_data; // Not owned. const void* src_data; // Not owned. uint32_t size; }; class BinaryReaderInterpreter : public BinaryReaderNop { public: BinaryReaderInterpreter(InterpreterEnvironment* env, DefinedInterpreterModule* module, size_t istream_offset, BinaryErrorHandler* error_handler); std::unique_ptr ReleaseOutputBuffer(); size_t get_istream_offset() { return istream_offset; } // Implement BinaryReader. virtual bool OnError(const char* message); virtual Result EndModule(); virtual Result OnTypeCount(uint32_t count); virtual Result OnType(uint32_t index, uint32_t param_count, Type* param_types, uint32_t result_count, Type* result_types); virtual Result OnImportCount(uint32_t count); virtual Result OnImport(uint32_t index, StringSlice module_name, StringSlice field_name); virtual Result OnImportFunc(uint32_t import_index, StringSlice module_name, StringSlice field_name, uint32_t func_index, uint32_t sig_index); virtual Result OnImportTable(uint32_t import_index, StringSlice module_name, StringSlice field_name, uint32_t table_index, Type elem_type, const Limits* elem_limits); virtual Result OnImportMemory(uint32_t import_index, StringSlice module_name, StringSlice field_name, uint32_t memory_index, const Limits* page_limits); virtual Result OnImportGlobal(uint32_t import_index, StringSlice module_name, StringSlice field_name, uint32_t global_index, Type type, bool mutable_); virtual Result OnFunctionCount(uint32_t count); virtual Result OnFunction(uint32_t index, uint32_t sig_index); virtual Result OnTable(uint32_t index, Type elem_type, const Limits* elem_limits); virtual Result OnMemory(uint32_t index, const Limits* limits); virtual Result OnGlobalCount(uint32_t count); virtual Result BeginGlobal(uint32_t index, Type type, bool mutable_); virtual Result EndGlobalInitExpr(uint32_t index); virtual Result OnExport(uint32_t index, ExternalKind kind, uint32_t item_index, StringSlice name); virtual Result OnStartFunction(uint32_t func_index); virtual Result BeginFunctionBody(uint32_t index); virtual Result OnLocalDeclCount(uint32_t count); virtual Result OnLocalDecl(uint32_t decl_index, uint32_t count, Type type); virtual Result OnBinaryExpr(Opcode opcode); virtual Result OnBlockExpr(uint32_t num_types, Type* sig_types); virtual Result OnBrExpr(uint32_t depth); virtual Result OnBrIfExpr(uint32_t depth); virtual Result OnBrTableExpr(uint32_t num_targets, uint32_t* target_depths, uint32_t default_target_depth); virtual Result OnCallExpr(uint32_t func_index); virtual Result OnCallIndirectExpr(uint32_t sig_index); virtual Result OnCompareExpr(Opcode opcode); virtual Result OnConvertExpr(Opcode opcode); virtual Result OnCurrentMemoryExpr(); virtual Result OnDropExpr(); virtual Result OnElseExpr(); virtual Result OnEndExpr(); virtual Result OnF32ConstExpr(uint32_t value_bits); virtual Result OnF64ConstExpr(uint64_t value_bits); virtual Result OnGetGlobalExpr(uint32_t global_index); virtual Result OnGetLocalExpr(uint32_t local_index); virtual Result OnGrowMemoryExpr(); virtual Result OnI32ConstExpr(uint32_t value); virtual Result OnI64ConstExpr(uint64_t value); virtual Result OnIfExpr(uint32_t num_types, Type* sig_types); virtual Result OnLoadExpr(Opcode opcode, uint32_t alignment_log2, uint32_t offset); virtual Result OnLoopExpr(uint32_t num_types, Type* sig_types); virtual Result OnNopExpr(); virtual Result OnReturnExpr(); virtual Result OnSelectExpr(); virtual Result OnSetGlobalExpr(uint32_t global_index); virtual Result OnSetLocalExpr(uint32_t local_index); virtual Result OnStoreExpr(Opcode opcode, uint32_t alignment_log2, uint32_t offset); virtual Result OnTeeLocalExpr(uint32_t local_index); virtual Result OnUnaryExpr(Opcode opcode); virtual Result OnUnreachableExpr(); virtual Result EndFunctionBody(uint32_t index); virtual Result EndElemSegmentInitExpr(uint32_t index); virtual Result OnElemSegmentFunctionIndex(uint32_t index, uint32_t func_index); virtual Result OnDataSegmentData(uint32_t index, const void* data, uint32_t size); virtual Result OnInitExprF32ConstExpr(uint32_t index, uint32_t value); virtual Result OnInitExprF64ConstExpr(uint32_t index, uint64_t value); virtual Result OnInitExprGetGlobalExpr(uint32_t index, uint32_t global_index); virtual Result OnInitExprI32ConstExpr(uint32_t index, uint32_t value); virtual Result OnInitExprI64ConstExpr(uint32_t index, uint64_t value); private: Label* GetLabel(uint32_t depth); Label* TopLabel(); void PushLabel(uint32_t offset, uint32_t fixup_offset); void PopLabel(); bool HandleError(uint32_t offset, const char* message); void PrintError(const char* format, ...); static void OnTypecheckerError(const char* msg, void* user_data); uint32_t TranslateSigIndexToEnv(uint32_t sig_index); InterpreterFuncSignature* GetSignatureByEnvIndex(uint32_t sig_index); InterpreterFuncSignature* GetSignatureByModuleIndex(uint32_t sig_index); uint32_t TranslateFuncIndexToEnv(uint32_t func_index); uint32_t TranslateModuleFuncIndexToDefined(uint32_t func_index); InterpreterFunc* GetFuncByEnvIndex(uint32_t func_index); InterpreterFunc* GetFuncByModuleIndex(uint32_t func_index); uint32_t TranslateGlobalIndexToEnv(uint32_t global_index); InterpreterGlobal* GetGlobalByEnvIndex(uint32_t global_index); InterpreterGlobal* GetGlobalByModuleIndex(uint32_t global_index); Type GetGlobalTypeByModuleIndex(uint32_t global_index); uint32_t TranslateLocalIndex(uint32_t local_index); Type GetLocalTypeByIndex(InterpreterFunc* func, uint32_t local_index); uint32_t GetIstreamOffset(); Result EmitDataAt(size_t offset, const void* data, size_t size); Result EmitData(const void* data, size_t size); Result EmitOpcode(Opcode opcode); Result EmitOpcode(InterpreterOpcode opcode); Result EmitI8(uint8_t value); Result EmitI32(uint32_t value); Result EmitI64(uint64_t value); Result EmitI32At(uint32_t offset, uint32_t value); Result EmitDropKeep(uint32_t drop, uint8_t keep); Result AppendFixup(Uint32VectorVector* fixups_vector, uint32_t index); Result EmitBrOffset(uint32_t depth, uint32_t offset); Result GetBrDropKeepCount(uint32_t depth, uint32_t* out_drop_count, uint32_t* out_keep_count); Result GetReturnDropKeepCount(uint32_t* out_drop_count, uint32_t* out_keep_count); Result EmitBr(uint32_t depth, uint32_t drop_count, uint32_t keep_count); Result EmitBrTableOffset(uint32_t depth); Result FixupTopLabel(); Result EmitFuncOffset(DefinedInterpreterFunc* func, uint32_t func_index); Result CheckLocal(uint32_t local_index); Result CheckGlobal(uint32_t global_index); Result CheckImportKind(InterpreterImport* import, ExternalKind expected_kind); Result CheckImportLimits(const Limits* declared_limits, const Limits* actual_limits); Result CheckHasMemory(Opcode opcode); Result CheckAlign(uint32_t alignment_log2, uint32_t natural_alignment); Result AppendExport(InterpreterModule* module, ExternalKind kind, uint32_t item_index, StringSlice name); PrintErrorCallback MakePrintErrorCallback(); static void OnHostImportPrintError(const char* msg, void* user_data); BinaryErrorHandler* error_handler = nullptr; InterpreterEnvironment* env = nullptr; DefinedInterpreterModule* module = nullptr; DefinedInterpreterFunc* current_func = nullptr; TypeCheckerErrorHandler tc_error_handler; TypeChecker typechecker; std::vector