From ca9ccccd10d1975eb117dd9ce05a189270f2fb01 Mon Sep 17 00:00:00 2001 From: Ben Smith Date: Thu, 30 Mar 2017 14:17:29 -0700 Subject: Use classes + virtual functions for BinaryReader (#376) This adds a few new classes: * BinaryReader: the abstract base class * BinaryReaderNop: implements all of BinaryReader, but does nothing * BinaryReaderLogging: logs calls through BinaryReader, and forwards to another BinaryReader Typically this means we can remove the Context structs from these implementations, since that data can just move into the BinaryReader subclasses. I also took the opportunity to rename the new member functions to MixedCase instead of snake_case, since that's more common in C++. --- src/binary-reader-interpreter.cc | 1763 +++++++++++++++++++------------------- 1 file changed, 886 insertions(+), 877 deletions(-) (limited to 'src/binary-reader-interpreter.cc') diff --git a/src/binary-reader-interpreter.cc b/src/binary-reader-interpreter.cc index b8948c0a..b22a4472 100644 --- a/src/binary-reader-interpreter.cc +++ b/src/binary-reader-interpreter.cc @@ -23,7 +23,7 @@ #include -#include "binary-reader.h" +#include "binary-reader-nop.h" #include "interpreter.h" #include "type-checker.h" #include "writer.h" @@ -34,27 +34,6 @@ return Result::Error; \ } while (0) -#define CHECK_LOCAL(ctx, local_index) \ - do { \ - uint32_t max_local_index = \ - (ctx)->current_func->param_and_local_types.size(); \ - if ((local_index) >= max_local_index) { \ - print_error((ctx), "invalid local_index: %d (max %d)", (local_index), \ - max_local_index); \ - return Result::Error; \ - } \ - } while (0) - -#define CHECK_GLOBAL(ctx, global_index) \ - do { \ - uint32_t max_global_index = (ctx)->global_index_mapping.size(); \ - if ((global_index) >= max_global_index) { \ - print_error((ctx), "invalid global_index: %d (max %d)", (global_index), \ - max_global_index); \ - return Result::Error; \ - } \ - } while (0) - namespace wabt { namespace { @@ -72,14 +51,219 @@ struct Label { Label::Label(uint32_t offset, uint32_t fixup_offset) : offset(offset), fixup_offset(fixup_offset) {} -struct Context { - Context(); +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); + + Result Init(); + void StealOutputBuffer(OutputBuffer*); + 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); - BinaryReader* reader = nullptr; BinaryErrorHandler* error_handler = nullptr; InterpreterEnvironment* env = nullptr; DefinedInterpreterModule* module = nullptr; DefinedInterpreterFunc* current_func = nullptr; + TypeCheckerErrorHandler tc_error_handler; TypeChecker typechecker; std::vector