From c062e792f44a0b668124a27a81e1b582f51da495 Mon Sep 17 00:00:00 2001 From: Adam Laszlo Kulcsar Date: Mon, 8 Jan 2024 12:39:06 +0100 Subject: [PATCH] [WIP] Implement live variable analysis Signed-off-by: Adam Laszlo Kulcsar --- notes.txt | 31 + src/interpreter/ByteCode.h | 30 + src/parser/WASMParser.cpp | 1894 +++++++++++++++++++++----- src/runtime/Module.cpp | 20 +- src/runtime/Module.h | 13 +- test/basic/local_initialization.wast | 63 + test/basic/local_livelyness.wast | 94 ++ test/basic/local_sets.wast | 110 ++ test/basic/useless_locals.wast | 8 + 9 files changed, 1907 insertions(+), 356 deletions(-) create mode 100644 notes.txt create mode 100644 test/basic/local_initialization.wast create mode 100644 test/basic/local_livelyness.wast create mode 100644 test/basic/local_sets.wast create mode 100644 test/basic/useless_locals.wast diff --git a/notes.txt b/notes.txt new file mode 100644 index 000000000..6d99f88d4 --- /dev/null +++ b/notes.txt @@ -0,0 +1,31 @@ +live_analysis + +get-ből való kiindulás azért jobb mert valaminek be kell állítania az értékét + +egy adott getből keresem vissza hogy milyen utakon lehet visszamenni az őt beállító utasításokig +multimap jó + +listákban tartom az összes változóra a set-jeit és a get-jeit + +jump + sets [T,p] +T - target, ahova ugrunk +p - position, ahonnan ugrottunk ++ listában a set-ek amelyek abban a blokban vannak + +dump!!! - variableRange + +[] hátra +() előre + +s g +s ( g ) + +s [ ( g ) ] + +[ (s ) g ] + +[ s [ g ] g ] ( g ) + + + +s [ g ][ s g ] diff --git a/src/interpreter/ByteCode.h b/src/interpreter/ByteCode.h index 38cb8fac6..1dd6b60bb 100644 --- a/src/interpreter/ByteCode.h +++ b/src/interpreter/ByteCode.h @@ -665,6 +665,7 @@ class BinaryOperation : public ByteCode { const ByteCodeStackOffset* srcOffset() const { return m_srcOffset; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } + void setSrcOffset(ByteCodeStackOffset o, size_t index) { m_srcOffset[index] = o; } #if !defined(NDEBUG) void dump(size_t pos) { @@ -707,6 +708,14 @@ class UnaryOperation : public ByteCode { } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset newOffset) + { + m_dstOffset = newOffset; + } + void setSrcOffset(ByteCodeStackOffset newOffset) + { + m_srcOffset = newOffset; + } #if !defined(NDEBUG) void dump(size_t pos) { @@ -876,6 +885,14 @@ class Move : public ByteCode { ByteCodeStackOffset srcOffset() const { return m_srcOffset; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset newOffset) + { + m_dstOffset = newOffset; + } + void setSrcOffset(ByteCodeStackOffset newOffset) + { + m_srcOffset = newOffset; + } protected: ByteCodeStackOffset m_srcOffset; @@ -977,7 +994,9 @@ class Load32 : public ByteCode { } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } + void setSrcOffset(ByteCodeStackOffset o) { m_srcOffset = o; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1029,7 +1048,9 @@ class Store32 : public ByteCode { } ByteCodeStackOffset src0Offset() const { return m_src0Offset; } + void setSrc0Offset(ByteCodeStackOffset o) { m_src0Offset = o; } ByteCodeStackOffset src1Offset() const { return m_src1Offset; } + void setSrc1Offset(ByteCodeStackOffset o) { m_src1Offset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1170,11 +1191,15 @@ class Select : public ByteCode { } ByteCodeStackOffset condOffset() const { return m_condOffset; } + void setCondOffset(ByteCodeStackOffset o) { m_condOffset = o; } uint16_t valueSize() const { return m_valueSize; } bool isFloat() const { return m_isFloat != 0; } ByteCodeStackOffset src0Offset() const { return m_src0Offset; } + void setSrc0Offset(ByteCodeStackOffset o) { m_src0Offset = o; } ByteCodeStackOffset src1Offset() const { return m_src1Offset; } + void setSrc1Offset(ByteCodeStackOffset o) { m_src1Offset = o; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1414,7 +1439,9 @@ class MemoryLoad : public ByteCode { uint32_t offset() const { return m_offset; } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } + void setSrcOffset(ByteCodeStackOffset o) { m_srcOffset = o; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1512,7 +1539,9 @@ class MemoryStore : public ByteCode { uint32_t offset() const { return m_offset; } ByteCodeStackOffset src0Offset() const { return m_src0Offset; } + void setSrc0Offset(ByteCodeStackOffset o) { m_src0Offset = o; } ByteCodeStackOffset src1Offset() const { return m_src1Offset; } + void setSrc1Offset(ByteCodeStackOffset o) { m_src1Offset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -2063,6 +2092,7 @@ class GlobalGet32 : public ByteCode { } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } uint32_t index() const { return m_index; } #if !defined(NDEBUG) diff --git a/src/parser/WASMParser.cpp b/src/parser/WASMParser.cpp index 08152d5ef..d1d4166f7 100644 --- a/src/parser/WASMParser.cpp +++ b/src/parser/WASMParser.cpp @@ -15,15 +15,96 @@ */ #include "Walrus.h" -#include "parser/WASMParser.h" #include "interpreter/ByteCode.h" -#include "runtime/Store.h" +#include "parser/WASMParser.h" #include "runtime/Module.h" +#include "runtime/Store.h" +#include "runtime/Value.h" #include "wabt/walrus/binary-reader-walrus.h" namespace wabt { +bool isWalrusBinaryOperation(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) +#undef GENERATE_BINARY_CODE_CASE + return true; + default: + return false; + } +} + +bool isWalrusUnaryOperation(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { +#define GENERATE_UNARY_CODE_CASE(name, ...) case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_UNARY_OP_2(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_CONVERT_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OTHER(GENERATE_UNARY_CODE_CASE) +#undef GENERATE_UNARY_CODE_CASE + return true; + default: + return false; + } +} + +bool isWalrusLoadOperation(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: + return true; + default: + return false; + } +} + +bool isWalrusMemoryLoad(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + return true; + default: + return false; + } +} + +bool isWalrusStoreOperation(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: + return true; + default: + return false; + } +} + +bool isWalrusMemoryStore(Walrus::ByteCode::Opcode opcode) +{ + switch (opcode) { +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + return true; + default: + return false; + } +} + enum class WASMOpcode : size_t { #define WABT_OPCODE(rtype, type1, type2, type3, memSize, prefix, code, name, \ text, decomp) \ @@ -43,7 +124,7 @@ struct WASMCodeInfo { WASMOpcode m_code; CodeType m_resultType; CodeType m_paramTypes[3]; - const char* m_name; + const char *m_name; size_t stackShrinkSize() const { @@ -151,9 +232,51 @@ static Walrus::SegmentMode toSegmentMode(uint8_t flags) class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { private: + struct variableRangeInfo { + Walrus::Value::Type type; + size_t start; + size_t end; + std::vector sets; + }; + + struct block { + enum blockType { + forwards, + backwards, + tryCatch, + }; + + size_t jumpPos; + std::vector setVariables; + blockType jumpType; + + + block(size_t jumpPos, size_t target) + : jumpPos(jumpPos) + { + jumpType = target < jumpPos ? block::backwards : block::forwards; + setVariables = {}; + } + }; + + struct variableInfo { + Walrus::Value::Type type; + bool free; + size_t pos; + size_t originalPos; + size_t firstPos; + size_t start; + size_t end; + +#if !defined(NDEBUG) + std::vector> assignedRanges; +#endif + }; + struct VMStackInfo { public: - VMStackInfo(WASMBinaryReader& reader, Walrus::Value::Type valueType, size_t position, size_t nonOptimizedPosition, size_t localIndex) + VMStackInfo(WASMBinaryReader &reader, Walrus::Value::Type valueType, + size_t position, size_t nonOptimizedPosition, size_t localIndex) : m_reader(reader) , m_valueType(valueType) , m_position(position) @@ -162,7 +285,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - VMStackInfo(const VMStackInfo& src) + VMStackInfo(const VMStackInfo &src) : m_reader(src.m_reader) , m_valueType(src.m_valueType) , m_position(src.m_position) @@ -171,11 +294,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - ~VMStackInfo() - { - } + ~VMStackInfo() {} - const VMStackInfo& operator=(const VMStackInfo& src) + const VMStackInfo &operator=(const VMStackInfo &src) { m_valueType = src.m_valueType; m_position = src.m_position; @@ -194,38 +315,23 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_localIndex = std::numeric_limits::max(); } - size_t position() const - { - return m_position; - } + size_t position() const { return m_position; } - void setPosition(size_t position) - { - m_position = position; - } + void setPosition(size_t position) { m_position = position; } - Walrus::Value::Type valueType() const - { - return m_valueType; - } + Walrus::Value::Type valueType() const { return m_valueType; } size_t stackAllocatedSize() const { return Walrus::valueStackAllocatedSize(m_valueType); } - size_t nonOptimizedPosition() const - { - return m_nonOptimizedPosition; - } + size_t nonOptimizedPosition() const { return m_nonOptimizedPosition; } - size_t localIndex() const - { - return m_localIndex; - } + size_t localIndex() const { return m_localIndex; } private: - WASMBinaryReader& m_reader; + WASMBinaryReader &m_reader; Walrus::Value::Type m_valueType; size_t m_position; // effective position (local values will have different position) size_t m_nonOptimizedPosition; // non-optimized position (same with m_functionStackSizeSoFar) @@ -262,24 +368,27 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { std::vector m_jumpToEndBrInfo; - BlockInfo(BlockType type, Type returnValueType, WASMBinaryReader& binaryReader) + BlockInfo(BlockType type, Type returnValueType, + WASMBinaryReader &binaryReader) : m_blockType(type) , m_returnValueType(returnValueType) , m_position(0) , m_functionStackSizeSoFar(binaryReader.m_functionStackSizeSoFar) - , m_shouldRestoreVMStackAtEnd((m_returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[m_returnValueType]->result().size()) - || m_returnValueType != Type::Void) + , m_shouldRestoreVMStackAtEnd( + (m_returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[m_returnValueType]->result().size()) || m_returnValueType != Type::Void) , m_byteCodeGenerationStopped(false) , m_seenBranch(false) { if (returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[returnValueType]->param().size()) { // record parameter positions - auto& param = binaryReader.m_result.m_functionTypes[returnValueType]->param(); + auto ¶m = binaryReader.m_result.m_functionTypes[returnValueType]->param(); auto endIter = binaryReader.m_vmStack.rbegin() + param.size(); auto iter = binaryReader.m_vmStack.rbegin(); while (iter != endIter) { if (iter->position() != iter->nonOptimizedPosition()) { - binaryReader.generateMoveCodeIfNeeds(iter->position(), iter->nonOptimizedPosition(), iter->valueType()); + binaryReader.generateMoveCodeIfNeeds(iter->position(), + iter->nonOptimizedPosition(), + iter->valueType()); iter->setPosition(iter->nonOptimizedPosition()); if (binaryReader.m_preprocessData.m_inPreprocess && iter->hasValidLocalIndex()) { size_t pos = *binaryReader.m_readerOffsetPointer; @@ -306,8 +415,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } }; - size_t* m_readerOffsetPointer; - const uint8_t* m_readerDataPointer; + size_t *m_readerOffsetPointer; + const uint8_t *m_readerDataPointer; size_t m_codeStartOffset; size_t m_codeEndOffset; @@ -338,7 +447,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { std::vector m_usageInfo; }; - PreprocessData(WASMBinaryReader& reader) + PreprocessData(WASMBinaryReader &reader) : m_inPreprocess(false) , m_reader(reader) { @@ -357,7 +466,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_reader.m_blockInfo.size()) { m_reader.m_blockInfo.back().m_seenBranch = true; } - for (auto& info : m_localVariableInfo) { + for (auto &info : m_localVariableInfo) { info.m_writePlacesBetweenBranches.clear(); } } @@ -368,16 +477,18 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_inPreprocess) { size_t pushCount = 0; size_t pos = *m_reader.m_readerOffsetPointer; - for (const auto& stack : m_reader.m_vmStack) { + for (const auto &stack : m_reader.m_vmStack) { if (stack.localIndex() == localIndex) { pushCount++; } } - m_localVariableInfo[localIndex].m_usageInfo.push_back(LocalVariableInfo::UsageInfo(pos, pushCount)); + m_localVariableInfo[localIndex].m_usageInfo.push_back( + LocalVariableInfo::UsageInfo(pos, pushCount)); if (!m_localVariableInfo[localIndex].m_needsExplicitInitOnStartup) { - if (!m_localVariableInfo[localIndex].m_writePlacesBetweenBranches.size()) { + if (!m_localVariableInfo[localIndex] + .m_writePlacesBetweenBranches.size()) { bool writeFound = false; - const auto& definitelyWritePlaces = m_localVariableInfo[localIndex].m_definitelyWritePlaces; + const auto &definitelyWritePlaces = m_localVariableInfo[localIndex].m_definitelyWritePlaces; for (size_t i = 0; i < definitelyWritePlaces.size(); i++) { if (definitelyWritePlaces[i] < pos) { writeFound = true; @@ -415,14 +526,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } if (isDefinitelyWritePlaces) { - m_localVariableInfo[localIndex].m_definitelyWritePlaces.push_back(pos); + m_localVariableInfo[localIndex].m_definitelyWritePlaces.push_back( + pos); } - m_localVariableInfo[localIndex].m_writePlacesBetweenBranches.push_back(pos); + m_localVariableInfo[localIndex].m_writePlacesBetweenBranches.push_back( + pos); } } - void addConstantData(const Walrus::Value& v) + void addConstantData(const Walrus::Value &v) { if (m_inPreprocess) { bool found = false; @@ -443,7 +556,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { constexpr size_t maxConstantData = WALRUS_ASSIGN_CONSTANT_ON_STACK_MAX_COUNT; if (m_constantData.size() > maxConstantData) { organizeConstantData(); - m_constantData.erase(m_constantData.end() - maxConstantData / 4, m_constantData.end()); + m_constantData.erase(m_constantData.end() - maxConstantData / 4, + m_constantData.end()); } } } @@ -451,26 +565,24 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { void organizeConstantData() { std::sort(m_constantData.begin(), m_constantData.end(), - [](const std::pair& a, const std::pair& b) -> bool { + [](const std::pair &a, + const std::pair &b) -> bool { return a.second > b.second; }); } - void organizeData() - { - organizeConstantData(); - } + void organizeData() { organizeConstantData(); } bool m_inPreprocess; - WASMBinaryReader& m_reader; + WASMBinaryReader &m_reader; std::vector m_localVariableInfo; // std::vector> m_constantData; }; bool m_inInitExpr; - Walrus::ModuleFunction* m_currentFunction; - Walrus::FunctionType* m_currentFunctionType; + Walrus::ModuleFunction *m_currentFunction; + Walrus::FunctionType *m_currentFunctionType; uint16_t m_initialFunctionStackSize; uint16_t m_functionStackSizeSoFar; @@ -494,11 +606,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } }; std::vector m_localInfo; + std::vector> m_optimizationCatchInfo; Walrus::Vector> m_memoryInitData; uint32_t m_elementTableIndex; - Walrus::Optional m_elementModuleFunction; + Walrus::Optional m_elementModuleFunction; Walrus::Vector> m_elementFunctionIndex; Walrus::SegmentMode m_segmentMode; @@ -510,12 +623,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { static const size_t s_noI32Eqz = SIZE_MAX - sizeof(Walrus::I32Eqz); size_t m_lastI32EqzPos; - virtual void OnSetOffsetAddress(size_t* ptr) override + virtual void OnSetOffsetAddress(size_t *ptr) override { m_readerOffsetPointer = ptr; } - virtual void OnSetDataAddress(const uint8_t* data) override + virtual void OnSetDataAddress(const uint8_t *data) override { m_readerDataPointer = data; } @@ -527,13 +640,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return pos; } - void pushVMStack(Walrus::Value::Type type, size_t pos, size_t localIndex = std::numeric_limits::max()) + void pushVMStack(Walrus::Value::Type type, size_t pos, + size_t localIndex = std::numeric_limits::max()) { if (localIndex != std::numeric_limits::max()) { m_preprocessData.addLocalVariableUsage(localIndex); } - m_vmStack.push_back(VMStackInfo(*this, type, pos, m_functionStackSizeSoFar, localIndex)); + m_vmStack.push_back( + VMStackInfo(*this, type, pos, m_functionStackSizeSoFar, localIndex)); size_t allocSize = Walrus::valueStackAllocatedSize(type); // FIXME too many stack usage. we could not support this(yet) ASSERT(m_functionStackSizeSoFar + allocSize <= std::numeric_limits::max()); @@ -556,7 +671,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_preprocessData.m_inPreprocess) { if (info.hasValidLocalIndex()) { size_t pos = *m_readerOffsetPointer; - auto iter = m_preprocessData.m_localVariableInfo[info.localIndex()].m_usageInfo.rbegin(); + auto iter = m_preprocessData.m_localVariableInfo[info.localIndex()] + .m_usageInfo.rbegin(); while (true) { ASSERT(iter != m_preprocessData.m_localVariableInfo[info.localIndex()].m_usageInfo.rend()); if (iter->m_endPosition == std::numeric_limits::max()) { @@ -571,7 +687,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return info; } - VMStackInfo& peekVMStackInfo() + VMStackInfo &peekVMStackInfo() { // FIXME This error can occur during the parsing process because of invalid wasm instructions // e.g. a function with no end opcode @@ -594,7 +710,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return peekVMStackInfo().valueType(); } - void beginFunction(Walrus::ModuleFunction* mf, bool inInitExpr) + void beginFunction(Walrus::ModuleFunction *mf, bool inInitExpr) { m_inInitExpr = inInitExpr; m_currentFunction = mf; @@ -620,12 +736,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } template - void pushByteCode(const CodeType& code, WASMOpcode opcode) + void pushByteCode(const CodeType &code, WASMOpcode opcode) { m_currentFunction->pushByteCode(code); } - void pushByteCode(const Walrus::I32Eqz& code, WASMOpcode opcode) + void pushByteCode(const Walrus::I32Eqz &code, WASMOpcode opcode) { m_lastI32EqzPos = m_currentFunction->currentByteCodeSize(); m_currentFunction->pushByteCode(code); @@ -634,14 +750,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { inline bool canBeInverted(size_t stackPos) { /** - * m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize() - * checks if last byteCode is I32Eqz + * m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == + * m_currentFunction->currentByteCodeSize() checks if last byteCode is + * I32Eqz * - * m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos - * checks if the output of I32Eqz is the input of JumpIfTrue/JumpIfFalse - */ - return (m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize()) - && (m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos); + * m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() + * == stackPos checks if the output of I32Eqz is the input of + * JumpIfTrue/JumpIfFalse + */ + return (m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize()) && (m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos); } Walrus::Optional lookaheadUnsigned8(size_t offset = 0) @@ -652,7 +769,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return Walrus::Optional(); } - std::pair, size_t> lookaheadUnsigned32(size_t offset = 0) // returns result value and data-length + std::pair, size_t> + lookaheadUnsigned32(size_t offset = 0) // returns result value and data-length { if (*m_readerOffsetPointer + offset < m_codeEndOffset) { uint32_t out = 0; @@ -663,7 +781,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return std::make_pair(Walrus::Optional(), 0); } - std::pair, size_t> readAheadLocalGetIfExists() // return localIndex and code length if exists + std::pair, size_t> + readAheadLocalGetIfExists() // return localIndex and code length if exists { Walrus::Optional mayLoadGetCode = lookaheadUnsigned8(); if (mayLoadGetCode.hasValue() && mayLoadGetCode.value() == 0x21) { @@ -704,8 +823,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } // should be allocated on the stack - static void* operator new(size_t) = delete; - static void* operator new[](size_t) = delete; + static void *operator new(size_t) = delete; + static void *operator new[](size_t) = delete; virtual void BeginModule(uint32_t version) override { @@ -719,18 +838,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // TODO reserve vector if possible } - virtual void OnFuncType(Index index, - Index paramCount, - Type* paramTypes, - Index resultCount, - Type* resultTypes) override + virtual void OnFuncType(Index index, Index paramCount, Type *paramTypes, + Index resultCount, Type *resultTypes) override { - Walrus::ValueTypeVector* param = new Walrus::ValueTypeVector(); + Walrus::ValueTypeVector *param = new Walrus::ValueTypeVector(); param->reserve(paramCount); for (size_t i = 0; i < paramCount; i++) { param->push_back(toValueKind(paramTypes[i])); } - Walrus::ValueTypeVector* result = new Walrus::ValueTypeVector(); + Walrus::ValueTypeVector *result = new Walrus::ValueTypeVector(); for (size_t i = 0; i < resultCount; i++) { result->push_back(toValueKind(resultTypes[i])); } @@ -743,62 +859,71 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_imports.reserve(count); } - virtual void OnImportFunc(Index importIndex, - std::string moduleName, - std::string fieldName, - Index funcIndex, + virtual void OnImportFunc(Index importIndex, std::string moduleName, + std::string fieldName, Index funcIndex, Index sigIndex) override { ASSERT(m_result.m_functions.size() == funcIndex); ASSERT(m_result.m_imports.size() == importIndex); - Walrus::FunctionType* ft = m_result.m_functionTypes[sigIndex]; - m_result.m_functions.push_back( - new Walrus::ModuleFunction(ft)); + Walrus::FunctionType *ft = m_result.m_functionTypes[sigIndex]; + m_result.m_functions.push_back(new Walrus::ModuleFunction(ft)); m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Function, - moduleName, fieldName, ft)); + Walrus::ImportType::Function, moduleName, fieldName, ft)); } - virtual void OnImportGlobal(Index importIndex, std::string moduleName, std::string fieldName, Index globalIndex, Type type, bool mutable_) override + virtual void OnImportGlobal(Index importIndex, std::string moduleName, + std::string fieldName, Index globalIndex, + Type type, bool mutable_) override { ASSERT(globalIndex == m_result.m_globalTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); - m_result.m_globalTypes.push_back(new Walrus::GlobalType(toValueKind(type), mutable_)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Global, - moduleName, fieldName, m_result.m_globalTypes[globalIndex])); + m_result.m_globalTypes.push_back( + new Walrus::GlobalType(toValueKind(type), mutable_)); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Global, moduleName, + fieldName, m_result.m_globalTypes[globalIndex])); } - virtual void OnImportTable(Index importIndex, std::string moduleName, std::string fieldName, Index tableIndex, Type type, size_t initialSize, size_t maximumSize) override + virtual void OnImportTable(Index importIndex, std::string moduleName, + std::string fieldName, Index tableIndex, Type type, + size_t initialSize, size_t maximumSize) override { ASSERT(tableIndex == m_result.m_tableTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); ASSERT(type == Type::FuncRef || type == Type::ExternRef); - m_result.m_tableTypes.push_back(new Walrus::TableType(type == Type::FuncRef ? Walrus::Value::Type::FuncRef : Walrus::Value::Type::ExternRef, initialSize, maximumSize)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Table, - moduleName, fieldName, m_result.m_tableTypes[tableIndex])); + m_result.m_tableTypes.push_back(new Walrus::TableType( + type == Type::FuncRef ? Walrus::Value::Type::FuncRef + : Walrus::Value::Type::ExternRef, + initialSize, maximumSize)); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Table, moduleName, fieldName, + m_result.m_tableTypes[tableIndex])); } - virtual void OnImportMemory(Index importIndex, std::string moduleName, std::string fieldName, Index memoryIndex, size_t initialSize, size_t maximumSize) override + virtual void OnImportMemory(Index importIndex, std::string moduleName, + std::string fieldName, Index memoryIndex, + size_t initialSize, size_t maximumSize) override { ASSERT(memoryIndex == m_result.m_memoryTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); - m_result.m_memoryTypes.push_back(new Walrus::MemoryType(initialSize, maximumSize)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Memory, - moduleName, fieldName, m_result.m_memoryTypes[memoryIndex])); + m_result.m_memoryTypes.push_back( + new Walrus::MemoryType(initialSize, maximumSize)); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Memory, moduleName, + fieldName, m_result.m_memoryTypes[memoryIndex])); } - virtual void OnImportTag(Index importIndex, std::string moduleName, std::string fieldName, Index tagIndex, Index sigIndex) override + virtual void OnImportTag(Index importIndex, std::string moduleName, + std::string fieldName, Index tagIndex, + Index sigIndex) override { ASSERT(tagIndex == m_result.m_tagTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); m_result.m_tagTypes.push_back(new Walrus::TagType(sigIndex)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Tag, - moduleName, fieldName, m_result.m_tagTypes[tagIndex])); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Tag, moduleName, fieldName, + m_result.m_tagTypes[tagIndex])); } virtual void OnExportCount(Index count) override @@ -806,10 +931,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_exports.reserve(count); } - virtual void OnExport(int kind, Index exportIndex, std::string name, Index itemIndex) override + virtual void OnExport(int kind, Index exportIndex, std::string name, + Index itemIndex) override { ASSERT(m_result.m_exports.size() == exportIndex); - m_result.m_exports.push_back(new Walrus::ExportType(static_cast(kind), name, itemIndex)); + m_result.m_exports.push_back(new Walrus::ExportType( + static_cast(kind), name, itemIndex)); } /* Table section */ @@ -818,11 +945,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_tableTypes.reserve(count); } - virtual void OnTable(Index index, Type type, size_t initialSize, size_t maximumSize) override + virtual void OnTable(Index index, Type type, size_t initialSize, + size_t maximumSize) override { ASSERT(index == m_result.m_tableTypes.size()); ASSERT(type == Type::FuncRef || type == Type::ExternRef); - m_result.m_tableTypes.push_back(new Walrus::TableType(type == Type::FuncRef ? Walrus::Value::Type::FuncRef : Walrus::Value::Type::ExternRef, initialSize, maximumSize)); + m_result.m_tableTypes.push_back(new Walrus::TableType( + type == Type::FuncRef ? Walrus::Value::Type::FuncRef + : Walrus::Value::Type::ExternRef, + initialSize, maximumSize)); } virtual void OnElemSegmentCount(Index count) override @@ -830,7 +961,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_elements.reserve(count); } - virtual void BeginElemSegment(Index index, Index tableIndex, uint8_t flags) override + virtual void BeginElemSegment(Index index, Index tableIndex, + uint8_t flags) override { m_elementTableIndex = tableIndex; m_elementModuleFunction = nullptr; @@ -839,7 +971,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void BeginElemSegmentInitExpr(Index index) override { - beginFunction(new Walrus::ModuleFunction(Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), true); + beginFunction( + new Walrus::ModuleFunction( + Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), + true); } virtual void EndElemSegmentInitExpr(Index index) override @@ -848,21 +983,21 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { endFunction(); } - virtual void OnElemSegmentElemType(Index index, Type elemType) override - { - } + virtual void OnElemSegmentElemType(Index index, Type elemType) override {} virtual void OnElemSegmentElemExprCount(Index index, Index count) override { m_elementFunctionIndex.reserve(count); } - virtual void OnElemSegmentElemExpr_RefNull(Index segmentIndex, Type type) override + virtual void OnElemSegmentElemExpr_RefNull(Index segmentIndex, + Type type) override { m_elementFunctionIndex.push_back(std::numeric_limits::max()); } - virtual void OnElemSegmentElemExpr_RefFunc(Index segmentIndex, Index funcIndex) override + virtual void OnElemSegmentElemExpr_RefFunc(Index segmentIndex, + Index funcIndex) override { m_elementFunctionIndex.push_back(funcIndex); } @@ -871,9 +1006,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { ASSERT(m_result.m_elements.size() == index); if (m_elementModuleFunction) { - m_result.m_elements.push_back(new Walrus::Element(m_segmentMode, m_elementTableIndex, m_elementModuleFunction.value(), std::move(m_elementFunctionIndex))); + m_result.m_elements.push_back(new Walrus::Element( + m_segmentMode, m_elementTableIndex, m_elementModuleFunction.value(), + std::move(m_elementFunctionIndex))); } else { - m_result.m_elements.push_back(new Walrus::Element(m_segmentMode, m_elementTableIndex, std::move(m_elementFunctionIndex))); + m_result.m_elements.push_back( + new Walrus::Element(m_segmentMode, m_elementTableIndex, + std::move(m_elementFunctionIndex))); } m_elementModuleFunction = nullptr; @@ -887,10 +1026,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_memoryTypes.reserve(count); } - virtual void OnMemory(Index index, uint64_t initialSize, uint64_t maximumSize) override + virtual void OnMemory(Index index, uint64_t initialSize, + uint64_t maximumSize) override { ASSERT(index == m_result.m_memoryTypes.size()); - m_result.m_memoryTypes.push_back(new Walrus::MemoryType(initialSize, maximumSize)); + m_result.m_memoryTypes.push_back( + new Walrus::MemoryType(initialSize, maximumSize)); } virtual void OnDataSegmentCount(Index count) override @@ -898,21 +1039,22 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_datas.reserve(count); } - virtual void BeginDataSegment(Index index, Index memoryIndex, uint8_t flags) override + virtual void BeginDataSegment(Index index, Index memoryIndex, + uint8_t flags) override { ASSERT(index == m_result.m_datas.size()); - beginFunction(new Walrus::ModuleFunction(Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), true); + beginFunction( + new Walrus::ModuleFunction( + Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), + true); } - virtual void BeginDataSegmentInitExpr(Index index) override - { - } + virtual void BeginDataSegmentInitExpr(Index index) override {} - virtual void EndDataSegmentInitExpr(Index index) override - { - } + virtual void EndDataSegmentInitExpr(Index index) override {} - virtual void OnDataSegmentData(Index index, const void* data, Address size) override + virtual void OnDataSegmentData(Index index, const void *data, + Address size) override { m_memoryInitData.resizeWithUninitializedValues(size); memcpy(m_memoryInitData.data(), data, size); @@ -921,7 +1063,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void EndDataSegment(Index index) override { ASSERT(index == m_result.m_datas.size()); - m_result.m_datas.push_back(new Walrus::Data(m_currentFunction, std::move(m_memoryInitData))); + m_result.m_datas.push_back( + new Walrus::Data(m_currentFunction, std::move(m_memoryInitData))); endFunction(); } @@ -936,7 +1079,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(m_currentFunction == nullptr); ASSERT(m_currentFunctionType == nullptr); ASSERT(m_result.m_functions.size() == index); - m_result.m_functions.push_back(new Walrus::ModuleFunction(m_result.m_functionTypes[sigIndex])); + m_result.m_functions.push_back( + new Walrus::ModuleFunction(m_result.m_functionTypes[sigIndex])); } virtual void OnGlobalCount(Index count) override @@ -947,29 +1091,24 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void BeginGlobal(Index index, Type type, bool mutable_) override { ASSERT(m_result.m_globalTypes.size() == index); - m_result.m_globalTypes.push_back(new Walrus::GlobalType(toValueKind(type), mutable_)); + m_result.m_globalTypes.push_back( + new Walrus::GlobalType(toValueKind(type), mutable_)); } virtual void BeginGlobalInitExpr(Index index) override { - auto ft = Walrus::Store::getDefaultFunctionType(m_result.m_globalTypes[index]->type()); - Walrus::ModuleFunction* mf = new Walrus::ModuleFunction(ft); + auto ft = Walrus::Store::getDefaultFunctionType( + m_result.m_globalTypes[index]->type()); + Walrus::ModuleFunction *mf = new Walrus::ModuleFunction(ft); m_result.m_globalTypes[index]->setFunction(mf); beginFunction(mf, true); } - virtual void EndGlobalInitExpr(Index index) override - { - endFunction(); - } + virtual void EndGlobalInitExpr(Index index) override { endFunction(); } - virtual void EndGlobal(Index index) override - { - } + virtual void EndGlobal(Index index) override {} - virtual void EndGlobalSection() override - { - } + virtual void EndGlobalSection() override {} virtual void OnTagCount(Index count) override { @@ -1035,6 +1174,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_shouldContinueToGenerateByteCode = true; m_currentFunction->m_byteCode.clear(); + + Walrus::ModuleFunction::CatchInfo *iter = m_currentFunction->m_catchInfo.begin(); + while (iter != m_currentFunction->m_catchInfo.end()) { + m_optimizationCatchInfo.push_back({ iter->m_tryStart, iter->m_catchStartPosition + iter->m_stackSizeToBe }); + iter++; + } + m_currentFunction->m_catchInfo.clear(); m_blockInfo.clear(); m_catchInfo.clear(); @@ -1054,13 +1200,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { #ifndef WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE #define WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE 64 #endif + // pack local variables if needs constexpr size_t enableLocalVaraiblePackingMinSize = WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE; + if (m_initialFunctionStackSize >= enableLocalVaraiblePackingMinSize) { - m_initialFunctionStackSize = m_currentFunctionType->paramStackSize(); + // m_initialFunctionStackSize = m_currentFunctionType->paramStackSize(); + // put already aligned variables first - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - auto& info = m_localInfo[i]; + for (size_t i = m_currentFunctionType->param().size(); + i < m_localInfo.size(); i++) { + auto &info = m_localInfo[i]; if (Walrus::hasCPUWordAlignedSize(info.m_valueType) || needsCPUWordAlignedAddress(info.m_valueType)) { info.m_position = m_initialFunctionStackSize; m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(info.m_valueType); @@ -1075,8 +1225,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } // pack rest values - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - auto& info = m_localInfo[i]; + for (size_t i = m_currentFunctionType->param().size(); + i < m_localInfo.size(); i++) { + auto &info = m_localInfo[i]; if (!Walrus::hasCPUWordAlignedSize(info.m_valueType) && !needsCPUWordAlignedAddress(info.m_valueType)) { info.m_position = m_initialFunctionStackSize; m_initialFunctionStackSize += Walrus::valueSize(info.m_valueType); @@ -1100,30 +1251,37 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_currentFunction->m_requiredStackSize = m_functionStackSizeSoFar; // Explicit init local variable if needs - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - if (m_preprocessData.m_localVariableInfo[i].m_needsExplicitInitOnStartup) { + for (size_t i = m_currentFunctionType->param().size(); + i < m_localInfo.size(); i++) { + if (m_preprocessData.m_localVariableInfo[i] + .m_needsExplicitInitOnStartup) { auto localPos = m_localInfo[i].m_position; auto size = Walrus::valueSize(m_localInfo[i].m_valueType); if (size == 4) { - pushByteCode(Walrus::Const32(localPos, 0), WASMOpcode::I32ConstOpcode); + pushByteCode(Walrus::Const32(localPos, 0), + WASMOpcode::I32ConstOpcode); } else if (size == 8) { - pushByteCode(Walrus::Const64(localPos, 0), WASMOpcode::I64ConstOpcode); + pushByteCode(Walrus::Const64(localPos, 0), + WASMOpcode::I64ConstOpcode); } else { ASSERT(size == 16); uint8_t empty[16] = { 0, }; - pushByteCode(Walrus::Const128(localPos, empty), WASMOpcode::V128ConstOpcode); + pushByteCode(Walrus::Const128(localPos, empty), + WASMOpcode::V128ConstOpcode); } } #if !defined(NDEBUG) - m_currentFunction->m_localDebugData.push_back(m_localInfo[i].m_position); + m_currentFunction->m_localDebugData.push_back( + Walrus::ModuleFunction::LocalDebugInfo{ + m_localInfo[i].m_position, {}, {} }); #endif } // init constant space for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) { - const auto& constValue = m_preprocessData.m_constantData[i].first; + const auto &constValue = m_preprocessData.m_constantData[i].first; auto constType = m_preprocessData.m_constantData[i].first.type(); auto constPos = m_preprocessData.m_constantData[i].second; size_t constSize = Walrus::valueSize(constType); @@ -1131,24 +1289,27 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { uint8_t constantBuffer[16]; constValue.writeToMemory(constantBuffer); if (constSize == 4) { - pushByteCode(Walrus::Const32(constPos, *reinterpret_cast(constantBuffer)), WASMOpcode::I32ConstOpcode); + pushByteCode(Walrus::Const32(constPos, *reinterpret_cast(constantBuffer)), + WASMOpcode::I32ConstOpcode); } else if (constSize == 8) { - pushByteCode(Walrus::Const64(constPos, *reinterpret_cast(constantBuffer)), WASMOpcode::I64ConstOpcode); + pushByteCode(Walrus::Const64(constPos, *reinterpret_cast(constantBuffer)), + WASMOpcode::I64ConstOpcode); } else { ASSERT(constSize == 16); - pushByteCode(Walrus::Const128(constPos, constantBuffer), WASMOpcode::V128ConstOpcode); + pushByteCode(Walrus::Const128(constPos, constantBuffer), + WASMOpcode::V128ConstOpcode); } #if !defined(NDEBUG) - m_currentFunction->m_constantDebugData.pushBack(m_preprocessData.m_constantData[i]); + m_currentFunction->m_constantDebugData.pushBack( + m_preprocessData.m_constantData[i]); #endif } } - virtual void OnOpcode(uint32_t opcode) override - { - } + virtual void OnOpcode(uint32_t opcode) override {} - uint16_t computeFunctionParameterOrResultOffsetCount(const Walrus::ValueTypeVector& types) + uint16_t computeFunctionParameterOrResultOffsetCount( + const Walrus::ValueTypeVector &types) { uint16_t result = 0; for (auto t : types) { @@ -1158,8 +1319,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } template - void generateCallExpr(CodeType* code, uint16_t parameterCount, uint16_t resultCount, - Walrus::FunctionType* functionType) + void generateCallExpr(CodeType *code, uint16_t parameterCount, + uint16_t resultCount, + Walrus::FunctionType *functionType) { size_t offsetIndex = 0; size_t siz = functionType->param().size(); @@ -1194,10 +1356,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto callPos = m_currentFunction->currentByteCodeSize(); auto parameterCount = computeFunctionParameterOrResultOffsetCount(functionType->param()); auto resultCount = computeFunctionParameterOrResultOffsetCount(functionType->result()); - pushByteCode(Walrus::Call(index, parameterCount, resultCount), WASMOpcode::CallOpcode); + pushByteCode(Walrus::Call(index, parameterCount, resultCount), + WASMOpcode::CallOpcode); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); auto code = m_currentFunction->peekByteCode(callPos); generateCallExpr(code, parameterCount, resultCount, functionType); @@ -1210,23 +1374,26 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto callPos = m_currentFunction->currentByteCodeSize(); auto parameterCount = computeFunctionParameterOrResultOffsetCount(functionType->param()); auto resultCount = computeFunctionParameterOrResultOffsetCount(functionType->result()); - pushByteCode(Walrus::CallIndirect(popVMStack(), tableIndex, functionType, parameterCount, resultCount), + pushByteCode(Walrus::CallIndirect(popVMStack(), tableIndex, functionType, + parameterCount, resultCount), WASMOpcode::CallIndirectOpcode); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); auto code = m_currentFunction->peekByteCode(callPos); generateCallExpr(code, parameterCount, resultCount, functionType); } - bool processConstValue(const Walrus::Value& value) + bool processConstValue(const Walrus::Value &value) { if (!m_inInitExpr) { m_preprocessData.addConstantData(value); if (!m_preprocessData.m_inPreprocess) { for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) { if (m_preprocessData.m_constantData[i].first == value) { - pushVMStack(value.type(), m_preprocessData.m_constantData[i].second); + pushVMStack(value.type(), + m_preprocessData.m_constantData[i].second); return true; } } @@ -1235,45 +1402,63 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return false; } - virtual void OnI32ConstExpr(uint32_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::I32, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::I32, + reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::I32), value), WASMOpcode::I32ConstOpcode); + pushByteCode( + Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::I32), + value), + WASMOpcode::I32ConstOpcode); } virtual void OnI64ConstExpr(uint64_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::I64, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::I64, + reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::I64), value), WASMOpcode::I64ConstOpcode); + pushByteCode( + Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::I64), + value), + WASMOpcode::I64ConstOpcode); } virtual void OnF32ConstExpr(uint32_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::F32, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::F32, + reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::F32), value), WASMOpcode::F32ConstOpcode); + pushByteCode( + Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::F32), + value), + WASMOpcode::F32ConstOpcode); } virtual void OnF64ConstExpr(uint64_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::F64, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::F64, + reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::F64), value), WASMOpcode::F64ConstOpcode); + pushByteCode( + Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::F64), + value), + WASMOpcode::F64ConstOpcode); } - virtual void OnV128ConstExpr(uint8_t* value) override + virtual void OnV128ConstExpr(uint8_t *value) override { if (processConstValue(Walrus::Value(Walrus::Value::Type::V128, value))) { return; } - pushByteCode(Walrus::Const128(computeExprResultPosition(Walrus::Value::Type::V128), value), WASMOpcode::V128ConstOpcode); + pushByteCode( + Walrus::Const128(computeExprResultPosition(Walrus::Value::Type::V128), + value), + WASMOpcode::V128ConstOpcode); } size_t computeExprResultPosition(Walrus::Value::Type type) @@ -1300,7 +1485,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { bool canUseDirectReference = true; size_t pos = *m_readerOffsetPointer; - for (const auto& r : m_preprocessData.m_localVariableInfo[localIndex].m_usageInfo) { + for (const auto &r : + m_preprocessData.m_localVariableInfo[localIndex].m_usageInfo) { if (r.m_startPosition <= pos && pos <= r.m_endPosition) { if (r.m_hasWriteUsage) { canUseDirectReference = false; @@ -1344,12 +1530,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto sz = Walrus::valueSize(valueType); auto stackPos = computeExprResultPosition(valueType); if (sz == 4) { - pushByteCode(Walrus::GlobalGet32(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet32(stackPos, index), + WASMOpcode::GlobalGetOpcode); } else if (sz == 8) { - pushByteCode(Walrus::GlobalGet64(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet64(stackPos, index), + WASMOpcode::GlobalGetOpcode); } else { ASSERT(sz == 16); - pushByteCode(Walrus::GlobalGet128(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet128(stackPos, index), + WASMOpcode::GlobalGetOpcode); } } @@ -1361,43 +1550,53 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == valueType); auto sz = Walrus::valueSize(valueType); if (sz == 4) { - pushByteCode(Walrus::GlobalSet32(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet32(stackPos, index), + WASMOpcode::GlobalSetOpcode); } else if (sz == 8) { - pushByteCode(Walrus::GlobalSet64(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet64(stackPos, index), + WASMOpcode::GlobalSetOpcode); } else { - pushByteCode(Walrus::GlobalSet128(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet128(stackPos, index), + WASMOpcode::GlobalSetOpcode); } popVMStack(); } - virtual void OnDropExpr() override - { - popVMStack(); - } + virtual void OnDropExpr() override { popVMStack(); } virtual void OnBinaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto src1 = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); generateBinaryCode(code, src0, src1, dst); } virtual void OnUnaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { case WASMOpcode::I32ReinterpretF32Opcode: case WASMOpcode::I64ReinterpretF64Opcode: case WASMOpcode::F32ReinterpretI32Opcode: case WASMOpcode::F64ReinterpretI64Opcode: - generateMoveCodeIfNeeds(src, dst, WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + generateMoveCodeIfNeeds(src, dst, + WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_resultType)); break; default: generateUnaryCode(code, src, dst); @@ -1408,13 +1607,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnTernaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[2]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[2]) + == peekVMStackValueType()); auto c = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto rhs = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto lhs = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { case WASMOpcode::V128BitSelectOpcode: pushByteCode(Walrus::V128BitSelect(lhs, rhs, c, dst), code); @@ -1432,13 +1638,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { bool isInverted = canBeInverted(stackPos); if (UNLIKELY(isInverted)) { - stackPos = m_currentFunction->peekByteCode(m_lastI32EqzPos)->srcOffset(); + stackPos = m_currentFunction + ->peekByteCode(m_lastI32EqzPos) + ->srcOffset(); m_currentFunction->resizeByteCode(m_lastI32EqzPos); m_lastI32EqzPos = s_noI32Eqz; } BlockInfo b(BlockInfo::IfElse, sigType, *this); - b.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJumpIf, b.m_position }); + b.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJumpIf, b.m_position }); m_blockInfo.push_back(b); if (UNLIKELY(isInverted)) { @@ -1449,7 +1658,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_preprocessData.seenBranch(); } - void restoreVMStackBy(const BlockInfo& blockInfo) + void restoreVMStackBy(const BlockInfo &blockInfo) { if (blockInfo.m_vmStack.size() <= m_vmStack.size()) { size_t diff = m_vmStack.size() - blockInfo.m_vmStack.size(); @@ -1462,30 +1671,33 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_functionStackSizeSoFar = blockInfo.m_functionStackSizeSoFar; } - void keepBlockResultsIfNeeds(BlockInfo& blockInfo) + void keepBlockResultsIfNeeds(BlockInfo &blockInfo) { auto dropSize = dropStackValuesBeforeBrIfNeeds(0); keepBlockResultsIfNeeds(blockInfo, dropSize); } - void keepBlockResultsIfNeeds(BlockInfo& blockInfo, const std::pair& dropSize) + void keepBlockResultsIfNeeds(BlockInfo &blockInfo, + const std::pair &dropSize) { if (blockInfo.m_shouldRestoreVMStackAtEnd) { if (!blockInfo.m_byteCodeGenerationStopped) { if (blockInfo.m_returnValueType.IsIndex()) { auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& result = ft->result(); + const auto &result = ft->result(); for (size_t i = 0; i < result.size(); i++) { ASSERT(peekVMStackValueType() == result[result.size() - i - 1]); auto info = peekVMStackInfo(); - generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), info.valueType()); + generateMoveCodeIfNeeds( + info.position(), info.nonOptimizedPosition(), info.valueType()); info.setPosition(info.nonOptimizedPosition()); popVMStack(); } } else if (blockInfo.m_returnValueType != Type::Void) { ASSERT(peekVMStackValueType() == toValueKind(blockInfo.m_returnValueType)); auto info = peekVMStackInfo(); - generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), info.valueType()); + generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), + info.valueType()); info.setPosition(info.nonOptimizedPosition()); popVMStack(); } @@ -1496,14 +1708,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnElseExpr() override { m_preprocessData.seenBranch(); - BlockInfo& blockInfo = m_blockInfo.back(); + BlockInfo &blockInfo = m_blockInfo.back(); keepBlockResultsIfNeeds(blockInfo); ASSERT(blockInfo.m_blockType == BlockInfo::IfElse); blockInfo.m_jumpToEndBrInfo.erase(blockInfo.m_jumpToEndBrInfo.begin()); if (!blockInfo.m_byteCodeGenerationStopped) { - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); pushByteCode(Walrus::Jump(), WASMOpcode::ElseOpcode); } @@ -1525,7 +1739,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_blockInfo.push_back(b); } - BlockInfo& findBlockInfoInBr(Index depth) + BlockInfo &findBlockInfoInBr(Index depth) { ASSERT(m_blockInfo.size()); auto iter = m_blockInfo.rbegin(); @@ -1544,7 +1758,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_blockInfo.size()) { m_resumeGenerateByteCodeAfterNBlockEnd = 1; - auto& blockInfo = m_blockInfo.back(); + auto &blockInfo = m_blockInfo.back(); blockInfo.m_shouldRestoreVMStackAtEnd = true; blockInfo.m_byteCodeGenerationStopped = true; } else { @@ -1577,12 +1791,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } else { if (iter->m_returnValueType.IsIndex()) { auto ft = m_result.m_functionTypes[iter->m_returnValueType]; - const auto& result = ft->result(); + const auto &result = ft->result(); for (size_t i = 0; i < result.size(); i++) { parameterSize += Walrus::valueStackAllocatedSize(result[i]); } } else if (iter->m_returnValueType != Type::Void) { - parameterSize += Walrus::valueStackAllocatedSize(toValueKind(iter->m_returnValueType)); + parameterSize += Walrus::valueStackAllocatedSize( + toValueKind(iter->m_returnValueType)); } } } @@ -1597,7 +1812,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return std::make_pair(dropValueSize, parameterSize); } - void generateMoveCodeIfNeeds(size_t srcPosition, size_t dstPosition, Walrus::Value::Type type) + void generateMoveCodeIfNeeds(size_t srcPosition, size_t dstPosition, + Walrus::Value::Type type) { if (srcPosition != dstPosition) { switch (type) { @@ -1663,7 +1879,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // reverse order copy to protect newer values remainSize = dropSize.second; while (true) { - generateMoveCodeIfNeeds(srcIter->position(), dstIter->nonOptimizedPosition(), srcIter->valueType()); + generateMoveCodeIfNeeds(srcIter->position(), + dstIter->nonOptimizedPosition(), + srcIter->valueType()); remainSize -= srcIter->stackAllocatedSize(); if (!remainSize) { break; @@ -1680,13 +1898,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return; } auto pos = m_currentFunction->currentByteCodeSize(); - auto offsetCount = computeFunctionParameterOrResultOffsetCount(m_currentFunctionType->result()); + auto offsetCount = computeFunctionParameterOrResultOffsetCount( + m_currentFunctionType->result()); pushByteCode(Walrus::End(offsetCount), WASMOpcode::EndOpcode); - auto& result = m_currentFunctionType->result(); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * offsetCount)); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); - Walrus::End* end = m_currentFunction->peekByteCode(pos); + auto &result = m_currentFunctionType->result(); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * offsetCount)); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); + Walrus::End *end = m_currentFunction->peekByteCode(pos); size_t offsetIndex = 0; for (size_t i = 0; i < result.size(); i++) { auto type = result[result.size() - 1 - i]; @@ -1740,7 +1960,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { generateFunctionReturnCode(true); return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (dropSize.second) { @@ -1749,17 +1969,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { size_t pos = m_currentFunction->currentByteCodeSize(); auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& param = ft->param(); + const auto ¶m = ft->param(); for (size_t i = 0; i < param.size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == param[param.size() - i - 1]); auto info = m_vmStack.rbegin() + i; - generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), info->valueType()); + generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), + info->valueType()); info->setPosition(info->nonOptimizedPosition()); } } if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrOpcode); @@ -1773,7 +1996,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto stackPos = popVMStack(); bool isInverted = canBeInverted(stackPos); if (UNLIKELY(isInverted)) { - stackPos = m_currentFunction->peekByteCode(m_lastI32EqzPos)->srcOffset(); + stackPos = m_currentFunction + ->peekByteCode(m_lastI32EqzPos) + ->srcOffset(); m_currentFunction->resizeByteCode(m_lastI32EqzPos); m_lastI32EqzPos = s_noI32Eqz; } @@ -1781,23 +2006,31 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // this case acts like return size_t pos = m_currentFunction->currentByteCodeSize(); if (UNLIKELY(isInverted)) { - pushByteCode(Walrus::JumpIfTrue(stackPos, sizeof(Walrus::JumpIfTrue) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); + pushByteCode( + Walrus::JumpIfTrue( + stackPos, sizeof(Walrus::JumpIfTrue) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), + WASMOpcode::BrIfOpcode); } else { - pushByteCode(Walrus::JumpIfFalse(stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); + pushByteCode( + Walrus::JumpIfFalse( + stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), + WASMOpcode::BrIfOpcode); } for (size_t i = 0; i < m_currentFunctionType->result().size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1]); } generateEndCode(); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (dropSize.second) { size_t pos = m_currentFunction->currentByteCodeSize(); @@ -1811,13 +2044,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrIfOpcode); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } } else if (blockInfo.m_blockType == BlockInfo::Loop && blockInfo.m_returnValueType.IsIndex() && m_result.m_functionTypes[blockInfo.m_returnValueType]->param().size()) { size_t pos = m_currentFunction->currentByteCodeSize(); @@ -1828,35 +2065,44 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& param = ft->param(); + const auto ¶m = ft->param(); for (size_t i = 0; i < param.size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == param[param.size() - i - 1]); auto info = m_vmStack.rbegin() + i; - generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), info->valueType()); + generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), + info->valueType()); info->setPosition(info->nonOptimizedPosition()); } auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrIfOpcode); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } } else { auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJumpIf, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJumpIf, + m_currentFunction->currentByteCodeSize() }); } if (UNLIKELY(isInverted)) { - pushByteCode(Walrus::JumpIfFalse(stackPos, offset), WASMOpcode::BrIfOpcode); + pushByteCode(Walrus::JumpIfFalse(stackPos, offset), + WASMOpcode::BrIfOpcode); } else { - pushByteCode(Walrus::JumpIfTrue(stackPos, offset), WASMOpcode::BrIfOpcode); + pushByteCode(Walrus::JumpIfTrue(stackPos, offset), + WASMOpcode::BrIfOpcode); } } } @@ -1872,7 +2118,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT((m_vmStack.rbegin() + i)->valueType() == m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1]); } #endif - *(int32_t*)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; + *(int32_t *)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; generateEndCode(); return; } @@ -1880,48 +2126,54 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (UNLIKELY(dropSize.second)) { - *(int32_t*)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; + *(int32_t *)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; OnBrExpr(depth); return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); offset = (int32_t)(blockInfo.m_position - brTableCode); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); offset = jumpOffset; - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsBrTable, brTableCode + jumpOffset }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsBrTable, brTableCode + jumpOffset }); } - *(int32_t*)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; + *(int32_t *)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; } - virtual void OnBrTableExpr(Index numTargets, Index* targetDepths, Index defaultTargetDepth) override + virtual void OnBrTableExpr(Index numTargets, Index *targetDepths, + Index defaultTargetDepth) override { m_preprocessData.seenBranch(); ASSERT(peekVMStackValueType() == Walrus::Value::I32); auto stackPos = popVMStack(); size_t brTableCode = m_currentFunction->currentByteCodeSize(); - pushByteCode(Walrus::BrTable(stackPos, numTargets), WASMOpcode::BrTableOpcode); + pushByteCode(Walrus::BrTable(stackPos, numTargets), + WASMOpcode::BrTableOpcode); if (numTargets) { - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(int32_t) * numTargets)); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode( + Walrus::ByteCode::pointerAlignedSize(sizeof(int32_t) * numTargets)); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); for (Index i = 0; i < numTargets; i++) { - emitBrTableCase(brTableCode, targetDepths[i], sizeof(Walrus::BrTable) + i * sizeof(int32_t)); + emitBrTableCase(brTableCode, targetDepths[i], + sizeof(Walrus::BrTable) + i * sizeof(int32_t)); } } // generate default - emitBrTableCase(brTableCode, defaultTargetDepth, Walrus::BrTable::offsetOfDefault()); + emitBrTableCase(brTableCode, defaultTargetDepth, + Walrus::BrTable::offsetOfDefault()); stopToGenerateByteCodeWhileBlockEnd(); } - virtual void OnSelectExpr(Index resultCount, Type* resultTypes) override + virtual void OnSelectExpr(Index resultCount, Type *resultTypes) override { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); ASSERT(resultCount == 0 || resultCount == 1); @@ -1932,7 +2184,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src0 = popVMStack(); auto dst = computeExprResultPosition(type); bool isFloat = type == Walrus::Value::F32 || type == Walrus::Value::F64; - pushByteCode(Walrus::Select(stackPos, Walrus::valueSize(type), isFloat, src0, src1, dst), WASMOpcode::SelectOpcode); + pushByteCode(Walrus::Select(stackPos, Walrus::valueSize(type), isFloat, + src0, src1, dst), + WASMOpcode::SelectOpcode); } virtual void OnThrowExpr(Index tagIndex) override @@ -1942,17 +2196,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { uint32_t offsetsSize = 0; if (tagIndex != std::numeric_limits::max()) { - offsetsSize = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]->param().size(); + offsetsSize = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()] + ->param() + .size(); } pushByteCode(Walrus::Throw(tagIndex, offsetsSize), WASMOpcode::ThrowOpcode); if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; - auto& param = functionType->param(); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * param.size())); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); - Walrus::Throw* code = m_currentFunction->peekByteCode(pos); + auto ¶m = functionType->param(); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * param.size())); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); + Walrus::Throw *code = m_currentFunction->peekByteCode(pos); for (size_t i = 0; i < param.size(); i++) { code->dataOffsets()[param.size() - i - 1] = (m_vmStack.rbegin() + i)->position(); } @@ -1977,7 +2234,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(m_blockInfo.back().m_blockType == BlockInfo::TryCatch); m_preprocessData.seenBranch(); - auto& blockInfo = m_blockInfo.back(); + auto &blockInfo = m_blockInfo.back(); keepBlockResultsIfNeeds(blockInfo); restoreVMStackBy(blockInfo); @@ -1988,13 +2245,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } if (!blockInfo.m_byteCodeGenerationStopped) { - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); pushByteCode(Walrus::Jump(), WASMOpcode::CatchOpcode); } blockInfo.m_byteCodeGenerationStopped = false; - m_catchInfo.push_back({ m_blockInfo.size(), m_blockInfo.back().m_position, tryEnd, m_currentFunction->currentByteCodeSize(), tagIndex }); + m_catchInfo.push_back({ m_blockInfo.size(), m_blockInfo.back().m_position, + tryEnd, m_currentFunction->currentByteCodeSize(), + tagIndex }); if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; @@ -2023,7 +2284,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryInit(memidx, segmentIndex, src0, src1, src2), WASMOpcode::MemoryInitOpcode); + pushByteCode(Walrus::MemoryInit(memidx, segmentIndex, src0, src1, src2), + WASMOpcode::MemoryInitOpcode); } virtual void OnMemoryCopyExpr(Index srcMemIndex, Index dstMemIndex) override @@ -2035,7 +2297,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryCopy(srcMemIndex, dstMemIndex, src0, src1, src2), WASMOpcode::MemoryCopyOpcode); + pushByteCode(Walrus::MemoryCopy(srcMemIndex, dstMemIndex, src0, src1, src2), + WASMOpcode::MemoryCopyOpcode); } virtual void OnMemoryFillExpr(Index memidx) override @@ -2047,7 +2310,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryFill(memidx, src0, src1, src2), WASMOpcode::MemoryFillOpcode); + pushByteCode(Walrus::MemoryFill(memidx, src0, src1, src2), + WASMOpcode::MemoryFillOpcode); } virtual void OnDataDropExpr(Index segmentIndex) override @@ -2060,13 +2324,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::MemoryGrow(memidx, src, dst), WASMOpcode::MemoryGrowOpcode); + pushByteCode(Walrus::MemoryGrow(memidx, src, dst), + WASMOpcode::MemoryGrowOpcode); } virtual void OnMemorySizeExpr(Index memidx) override { auto stackPos = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::MemorySize(memidx, stackPos), WASMOpcode::MemorySizeOpcode); + pushByteCode(Walrus::MemorySize(memidx, stackPos), + WASMOpcode::MemorySizeOpcode); } virtual void OnTableGetExpr(Index tableIndex) override @@ -2074,7 +2340,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); auto dst = computeExprResultPosition(m_result.m_tableTypes[tableIndex]->type()); - pushByteCode(Walrus::TableGet(tableIndex, src, dst), WASMOpcode::TableGetOpcode); + pushByteCode(Walrus::TableGet(tableIndex, src, dst), + WASMOpcode::TableGetOpcode); } virtual void OnTableSetExpr(Index tableIndex) override @@ -2083,7 +2350,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableSet(tableIndex, src0, src1), WASMOpcode::TableSetOpcode); + pushByteCode(Walrus::TableSet(tableIndex, src0, src1), + WASMOpcode::TableSetOpcode); } virtual void OnTableGrowExpr(Index tableIndex) override @@ -2093,13 +2361,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == m_result.m_tableTypes[tableIndex]->type()); auto src0 = popVMStack(); auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::TableGrow(tableIndex, src0, src1, dst), WASMOpcode::TableGrowOpcode); + pushByteCode(Walrus::TableGrow(tableIndex, src0, src1, dst), + WASMOpcode::TableGrowOpcode); } virtual void OnTableSizeExpr(Index tableIndex) override { auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::TableSize(tableIndex, dst), WASMOpcode::TableSizeOpcode); + pushByteCode(Walrus::TableSize(tableIndex, dst), + WASMOpcode::TableSizeOpcode); } virtual void OnTableCopyExpr(Index dst_index, Index src_index) override @@ -2110,7 +2380,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableCopy(dst_index, src_index, src0, src1, src2), WASMOpcode::TableCopyOpcode); + pushByteCode(Walrus::TableCopy(dst_index, src_index, src0, src1, src2), + WASMOpcode::TableCopyOpcode); } virtual void OnTableFillExpr(Index tableIndex) override @@ -2121,7 +2392,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableFill(tableIndex, src0, src1, src2), WASMOpcode::TableFillOpcode); + pushByteCode(Walrus::TableFill(tableIndex, src0, src1, src2), + WASMOpcode::TableFillOpcode); } virtual void OnElemDropExpr(Index segmentIndex) override @@ -2137,15 +2409,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableInit(tableIndex, segmentIndex, src0, src1, src2), WASMOpcode::TableInitOpcode); + pushByteCode(Walrus::TableInit(tableIndex, segmentIndex, src0, src1, src2), + WASMOpcode::TableInitOpcode); } - virtual void OnLoadExpr(int opcode, Index memidx, Address alignmentLog2, Address offset) override + virtual void OnLoadExpr(int opcode, Index memidx, Address alignmentLog2, + Address offset) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); if ((opcode == (int)WASMOpcode::I32LoadOpcode || opcode == (int)WASMOpcode::F32LoadOpcode) && offset == 0) { pushByteCode(Walrus::Load32(src, dst), code); } else if ((opcode == (int)WASMOpcode::I64LoadOpcode || opcode == (int)WASMOpcode::F64LoadOpcode) && offset == 0) { @@ -2155,12 +2432,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnStoreExpr(int opcode, Index memidx, Address alignmentLog2, Address offset) override + virtual void OnStoreExpr(int opcode, Index memidx, Address alignmentLog2, + Address offset) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto src1 = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src0 = popVMStack(); if ((opcode == (int)WASMOpcode::I32StoreOpcode || opcode == (int)WASMOpcode::F32StoreOpcode) && offset == 0) { pushByteCode(Walrus::Store32(src0, src1), code); @@ -2181,9 +2463,11 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { Walrus::ByteCodeStackOffset dst = computeExprResultPosition(toValueKind(type)); #if defined(WALRUS_32) - pushByteCode(Walrus::Const32(dst, Walrus::Value::Null), WASMOpcode::Const32Opcode); + pushByteCode(Walrus::Const32(dst, Walrus::Value::Null), + WASMOpcode::Const32Opcode); #else - pushByteCode(Walrus::Const64(dst, Walrus::Value::Null), WASMOpcode::Const64Opcode); + pushByteCode(Walrus::Const64(dst, Walrus::Value::Null), + WASMOpcode::Const64Opcode); #endif } @@ -2198,9 +2482,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { #endif } - virtual void OnNopExpr() override - { - } + virtual void OnNopExpr() override {} virtual void OnReturnExpr() override { @@ -2210,8 +2492,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnEndExpr() override { - // combining an i32.eqz at the end of a block followed by a JumpIf cannot be combined - // because it is possible to jump to the location after i32.eqz + // combining an i32.eqz at the end of a block followed by a JumpIf cannot be + // combined because it is possible to jump to the location after i32.eqz m_lastI32EqzPos = s_noI32Eqz; if (m_blockInfo.size()) { auto dropSize = dropStackValuesBeforeBrIfNeeds(0); @@ -2237,7 +2519,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { for (size_t i = 0; i < blockInfo.m_vmStack.size(); i++) { stackSizeToBe += m_vmStack[i].stackAllocatedSize(); } - m_currentFunction->m_catchInfo.push_back({ iter->m_tryStart, iter->m_tryEnd, iter->m_catchStart, stackSizeToBe, iter->m_tagIndex }); + m_currentFunction->m_catchInfo.push_back( + { iter->m_tryStart, iter->m_tryEnd, iter->m_catchStart, + stackSizeToBe, iter->m_tagIndex }); iter = m_catchInfo.erase(iter); } } @@ -2253,13 +2537,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { restoreVMStackBy(blockInfo); if (blockInfo.m_returnValueType.IsIndex()) { auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& param = ft->param(); + const auto ¶m = ft->param(); for (size_t i = 0; i < param.size(); i++) { ASSERT(peekVMStackValueType() == param[param.size() - i - 1]); popVMStack(); } - const auto& result = ft->result(); + const auto &result = ft->result(); for (size_t i = 0; i < result.size(); i++) { pushVMStack(result[i]); } @@ -2271,16 +2555,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { for (size_t i = 0; i < blockInfo.m_jumpToEndBrInfo.size(); i++) { switch (blockInfo.m_jumpToEndBrInfo[i].m_type) { case BlockInfo::JumpToEndBrInfo::IsJump: - m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position)->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); + m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position) + ->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); break; case BlockInfo::JumpToEndBrInfo::IsJumpIf: - m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position) + m_currentFunction + ->peekByteCode( + blockInfo.m_jumpToEndBrInfo[i].m_position) ->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); break; default: ASSERT(blockInfo.m_jumpToEndBrInfo[i].m_type == BlockInfo::JumpToEndBrInfo::IsBrTable); - int32_t* offset = m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position); + int32_t *offset = m_currentFunction->peekByteCode( + blockInfo.m_jumpToEndBrInfo[i].m_position); *offset = m_currentFunction->currentByteCodeSize() + (size_t)*offset - blockInfo.m_jumpToEndBrInfo[i].m_position; break; } @@ -2299,13 +2587,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void EndFunctionBody(Index index) override { + optimizeLocals(); m_lastI32EqzPos = s_noI32Eqz; #if !defined(NDEBUG) if (getenv("DUMP_BYTECODE") && strlen(getenv("DUMP_BYTECODE"))) { m_currentFunction->dumpByteCode(); } if (m_shouldContinueToGenerateByteCode) { - for (size_t i = 0; i < m_currentFunctionType->result().size() && m_vmStack.size(); i++) { + for (size_t i = 0; + i < m_currentFunctionType->result().size() && m_vmStack.size(); + i++) { ASSERT(popVMStackInfo().valueType() == m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1]); } ASSERT(m_vmStack.empty()); @@ -2317,12 +2608,14 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } // SIMD Instructions - virtual void OnLoadSplatExpr(int opcode, Index memidx, Address alignment_log2, Address offset) override + virtual void OnLoadSplatExpr(int opcode, Index memidx, Address alignment_log2, + Address offset) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { #define GENERATE_LOAD_CODE_CASE(name, ...) \ case WASMOpcode::name##Opcode: { \ @@ -2337,12 +2630,14 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnLoadZeroExpr(int opcode, Index memidx, Address alignment_log2, Address offset) override + virtual void OnLoadZeroExpr(int opcode, Index memidx, Address alignment_log2, + Address offset) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { case WASMOpcode::V128Load32ZeroOpcode: { pushByteCode(Walrus::V128Load32Zero(offset, src, dst), code); @@ -2362,28 +2657,39 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { auto code = static_cast(opcode); switch (code) { -#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ - case WASMOpcode::name##Opcode: { \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); \ - auto src = popVMStack(); \ - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); \ - pushByteCode(Walrus::name(static_cast(value), src, dst), code); \ - break; \ - } - -#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ - case WASMOpcode::name##Opcode: { \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); \ - auto src1 = popVMStack(); \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); \ - auto src0 = popVMStack(); \ - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); \ - pushByteCode(Walrus::name(static_cast(value), src0, src1, dst), code); \ - break; \ - } - - FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) - FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case WASMOpcode::name##Opcode: { \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[0]) \ + == peekVMStackValueType()); \ + auto src = popVMStack(); \ + auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_resultType)); \ + pushByteCode(Walrus::name(static_cast(value), src, dst), code); \ + break; \ + } + +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case WASMOpcode::name##Opcode: { \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[1]) \ + == peekVMStackValueType()); \ + auto src1 = popVMStack(); \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[0]) \ + == peekVMStackValueType()); \ + auto src0 = popVMStack(); \ + auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_resultType)); \ + pushByteCode(Walrus::name(static_cast(value), src0, src1, dst), \ + code); \ + break; \ + } + + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP( + GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP( + GENERATE_SIMD_REPLACE_LANE_CODE_CASE) #undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE #undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE default: @@ -2392,19 +2698,25 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdLoadLaneExpr(int opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override + virtual void OnSimdLoadLaneExpr(int opcode, Index memidx, + Address alignment_log2, Address offset, + uint64_t value) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { -#define GENERATE_LOAD_CODE_CASE(name, opType) \ - case WASMOpcode::name##Opcode: { \ - pushByteCode(Walrus::name(offset, src0, src1, static_cast(value), dst), code); \ - break; \ +#define GENERATE_LOAD_CODE_CASE(name, opType) \ + case WASMOpcode::name##Opcode: { \ + pushByteCode(Walrus::name(offset, src0, src1, \ + static_cast(value), \ + dst), \ + code); \ + break; \ } FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_LOAD_CODE_CASE) #undef GENERATE_LOAD_CODE_CASE @@ -2413,7 +2725,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdStoreLaneExpr(int opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override + virtual void OnSimdStoreLaneExpr(int opcode, Index memidx, + Address alignment_log2, Address offset, + uint64_t value) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); @@ -2421,10 +2735,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); switch (code) { -#define GENERATE_STORE_CODE_CASE(name, opType) \ - case WASMOpcode::name##Opcode: { \ - pushByteCode(Walrus::name(offset, src0, src1, static_cast(value)), code); \ - break; \ +#define GENERATE_STORE_CODE_CASE(name, opType) \ + case WASMOpcode::name##Opcode: { \ + pushByteCode( \ + Walrus::name(offset, src0, src1, \ + static_cast(value)), \ + code); \ + break; \ } FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_STORE_CODE_CASE) #undef GENERATE_STORE_CODE_CASE @@ -2433,18 +2750,21 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdShuffleOpExpr(int opcode, uint8_t* value) override + virtual void OnSimdShuffleOpExpr(int opcode, uint8_t *value) override { ASSERT(static_cast(opcode) == WASMOpcode::I8X16ShuffleOpcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); - pushByteCode(Walrus::I8X16Shuffle(src0, src1, dst, value), WASMOpcode::I8X16ShuffleOpcode); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + pushByteCode(Walrus::I8X16Shuffle(src0, src1, dst, value), + WASMOpcode::I8X16ShuffleOpcode); } - void generateBinaryCode(WASMOpcode code, size_t src0, size_t src1, size_t dst) + void generateBinaryCode(WASMOpcode code, size_t src0, size_t src1, + size_t dst) { switch (code) { #define GENERATE_BINARY_CODE_CASE(name, ...) \ @@ -2483,7 +2803,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - void generateMemoryLoadCode(WASMOpcode code, size_t offset, size_t src, size_t dst) + void generateMemoryLoadCode(WASMOpcode code, size_t offset, size_t src, + size_t dst) { switch (code) { #define GENERATE_LOAD_CODE_CASE(name, readType, writeType) \ @@ -2500,7 +2821,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - void generateMemoryStoreCode(WASMOpcode code, size_t offset, size_t src0, size_t src1) + void generateMemoryStoreCode(WASMOpcode code, size_t offset, size_t src0, + size_t src1) { switch (code) { #define GENERATE_STORE_CODE_CASE(name, readType, writeType) \ @@ -2529,13 +2851,874 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - Walrus::WASMParsingResult& parsingResult() { return m_result; } + Walrus::WASMParsingResult &parsingResult() { return m_result; } + + void optimizeLocals() + { + if (m_currentFunction->functionType()->param().size() == m_localInfo.size()) { + return; + } + + // variableRange & blocks stuct pair helyet + + // first = target of jump, second = the information of the block + std::multimap blocks; + std::vector variableRange; + std::vector ends; // szükséges? + throw + call, callindirect + // std::vector throws; + // std::vector calls; + // std::vector callIndirects; + + variableRange.reserve(m_localInfo.size()); + + size_t variableSize = m_localInfo.size(); + size_t paramSize = m_currentFunctionType->param().size(); + for (unsigned i = 0; i < variableSize; i++) { + if (i < paramSize) { + variableRange.push_back({ m_localInfo[i].m_valueType, 0, SIZE_MAX, {} }); + } else { + variableRange.push_back({ m_localInfo[i].m_valueType, SIZE_MAX, 0, {} }); + } + } + + size_t offset = 0; + size_t i = 0; + while (i < m_currentFunction->currentByteCodeSize()) { + Walrus::ByteCode *byteCode = reinterpret_cast( + const_cast(m_currentFunction->byteCode() + i)); + + size_t jumpOffset = SIZE_MAX; + size_t offsets[] = { SIZE_MAX, SIZE_MAX, SIZE_MAX }; + + switch (byteCode->opcode()) { +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffset()[1]; + break; + } +#undef GENERATE_BINARY_CODE_CASE +#define GENERATE_UNARY_CODE_CASE(name, ...) case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_UNARY_OP_2(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_CONVERT_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OTHER(GENERATE_UNARY_CODE_CASE) +#undef GENERATE_UNARY_CODE_CASE + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } + case Walrus::ByteCode::GlobalGet32Opcode: + case Walrus::ByteCode::GlobalGet64Opcode: + case Walrus::ByteCode::GlobalGet128Opcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + { + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } + case Walrus::ByteCode::SelectOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::JumpOpcode: { + jumpOffset = (size_t)std::abs((int64_t)(i + reinterpret_cast(byteCode)->offset())); + break; + } + case Walrus::ByteCode::JumpIfTrueOpcode: + case Walrus::ByteCode::JumpIfFalseOpcode: { + jumpOffset = (size_t)std::abs((int64_t)(i + reinterpret_cast(byteCode)->offset())); + break; + } + case Walrus::ByteCode::EndOpcode: { + ends.push_back(reinterpret_cast(byteCode)); + break; + } + default: { + i += byteCode->getSize(); + continue; + } + } + + for (size_t j = 0; j < m_localInfo.size(); j++) { + if (offsets[0] == SIZE_MAX && offsets[1] == SIZE_MAX && offsets[1] == SIZE_MAX) { + break; + } + + if (variableRange[j].end == SIZE_MAX) { + continue; + } + + if (m_localInfo[j].m_position == offsets[0] || m_localInfo[j].m_position == offsets[1] || m_localInfo[j].m_position == offsets[2]) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + variableRange[j].end = i; + } + if (m_localInfo[j].m_position == offsets[0]) { + variableRange[j].sets.push_back(i); + } + } + + // érdemes lehet előre hozni, az end nem biztos hogy kell + for (size_t j = 0; j < m_localInfo.size(); j++) { + for (auto &end : ends) { + for (size_t count = 0; count < end->offsetsSize(); count++) { + if (m_localInfo[j].m_position == end->resultOffsets()[count]) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + if (variableRange[j].end < i) { + variableRange[j].end = i; + } + } + } + } + } + + // br table is lehet kell ide + // jumpoffset >= 0-ra ki lehet cserélni + + if (jumpOffset != SIZE_MAX) { + blocks.insert(std::pair(jumpOffset, block(i, jumpOffset))); + } + + i += byteCode->getSize(); + } + + // forward és backward blockok külön kezelése + // az életciklust már nem csak előre hanem hátra is ki kell terjeszteni ! + + for (auto &elem : variableRange) { + if (elem.start == 0 && elem.end == SIZE_MAX) { + continue; + } + + for (auto &tryBlock : m_optimizationCatchInfo) { + if (elem.start > tryBlock.first && elem.end < tryBlock.second) { + elem.start = tryBlock.first; + elem.end = tryBlock.second; + } + } + + auto lowerbound = blocks.lower_bound(elem.start); + if (lowerbound != blocks.end()) { + size_t blockStart = 0; + switch ((*lowerbound).second.jumpType) { + case block::backwards: { + blockStart = (*lowerbound).first; + break; + } + case block::forwards: { + blockStart = (*lowerbound).second.jumpPos; + break; + } + default: { + ASSERT_NOT_REACHED(); + break; + } + } + + if (blockStart > elem.end) { + break; + } + + if ((*lowerbound).second.jumpType == block::backwards && elem.end < (*lowerbound).second.jumpPos) { + elem.end = (*lowerbound).second.jumpPos; + if (elem.start > (*lowerbound).first) { + elem.start = (*lowerbound).first; + } + } + } + } + + // for (auto &elem : variableRange) { + // size_t sets = elem.sets.size(); + // size_t i = elem.end; + + // if (sets == 0) { + // elem.start = 0; + // } + + // for (auto &block : blocks) { + // if (block.jumpType == block::backwards) { + // if (block.target < elem.end && block.jumpPos > elem.end) { + // elem.end = block.jumpPos; + // } + // if (block.target < elem.start && block.jumpPos > elem.start) { + // elem.start = block.target; + // } + // } + // } + // } + + Walrus::Value::Type valueTypes[] = { + Walrus::Value::Type::I32, Walrus::Value::Type::I64, + Walrus::Value::Type::F32, Walrus::Value::Type::F64, + Walrus::Value::Type::V128 + }; + size_t maxLives[] = { 0, 0, 0, 0, 0 }; + for (auto &type : valueTypes) { + i = 0; + size_t lives = 0; + std::vector rangesForType; + + for (auto &range : variableRange) { + if (range.end != SIZE_MAX && range.start != SIZE_MAX && range.type == type) { + rangesForType.push_back(range); + } + } + + while (i < m_currentFunction->currentByteCodeSize()) { + Walrus::ByteCode *byteCode = reinterpret_cast( + const_cast(m_currentFunction->byteCode() + i)); + + for (auto &range : rangesForType) { + if (range.start == i) { + lives++; + } + + maxLives[type] = std::max(maxLives[type], lives); + + if (range.end == i) { + lives--; + } + } + + i += byteCode->getSize(); + } + rangesForType.clear(); + } + + for (auto ¶m : m_currentFunctionType->param()) { + offset += Walrus::valueStackAllocatedSize(param); + } + + std::vector infos; + for (auto &type : valueTypes) { + for (int i = maxLives[type]; i > 0; i--) { + variableInfo var; + var.free = true; + var.type = type; + var.pos = offset; + var.originalPos = SIZE_MAX - 1; + var.firstPos = SIZE_MAX; + infos.push_back(var); + if (type == Walrus::Value::Type::I32 || type == Walrus::Value::Type::F32) { + offset += 4; + continue; + } + offset += Walrus::valueStackAllocatedSize(type); + } + } + + std::vector unsetVariables; + for (auto &info : infos) { + unsetVariables.push_back(info.pos); + } + + bool initsAreComplete = false; + for (size_t i = 0; i < m_currentFunction->currentByteCodeSize();) { + Walrus::ByteCode *byteCode = reinterpret_cast( + const_cast(m_currentFunction->byteCode() + i)); + + if (!initsAreComplete) { + switch (byteCode->opcode()) { + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + i += byteCode->getSize(); + continue; + } + default: { + initsAreComplete = true; + break; + } + } + } + + for (auto &info : infos) { + if (info.end < i && !info.free) { + info.free = true; + info.end = 0; + } + } + + size_t offsets[] = { SIZE_MAX, SIZE_MAX, SIZE_MAX, SIZE_MAX }; + switch (byteCode->opcode()) { +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) + { + Walrus::BinaryOperation *binOp = reinterpret_cast(byteCode); + offsets[0] = binOp->dstOffset(); + offsets[1] = binOp->srcOffset()[0]; + offsets[2] = binOp->srcOffset()[1]; + break; + } +#undef GENERATE_BINARY_CODE_CASE +#define GENERATE_UNARY_CODE_CASE(name, ...) case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_UNARY_OP_2(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_CONVERT_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OTHER(GENERATE_UNARY_CODE_CASE) +#undef GENERATE_UNARY_CODE_CASE + { + Walrus::UnaryOperation *unOp = reinterpret_cast(byteCode); + offsets[0] = unOp->dstOffset(); + offsets[1] = unOp->srcOffset(); + break; + } + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::MoveI32 *move = reinterpret_cast(byteCode); + offsets[0] = move->dstOffset(); + offsets[1] = move->srcOffset(); + break; + } + case Walrus::ByteCode::GlobalGet32Opcode: + case Walrus::ByteCode::GlobalGet64Opcode: + case Walrus::ByteCode::GlobalGet128Opcode: { + Walrus::GlobalGet32 *get = reinterpret_cast(byteCode); + offsets[0] = get->dstOffset(); + break; + } +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + offsets[0] = load->dstOffset(); + offsets[1] = load->srcOffset(); + break; + } +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + { + Walrus::MemoryStore *store = reinterpret_cast(byteCode); + offsets[1] = store->src0Offset(); + offsets[2] = store->src1Offset(); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + offsets[0] = load->dstOffset(); + offsets[1] = load->srcOffset(); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + offsets[1] = store->src0Offset(); + offsets[2] = store->src1Offset(); + + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + offsets[0] = select->dstOffset(); + offsets[1] = select->src0Offset(); + offsets[2] = select->src1Offset(); + offsets[3] = select->condOffset(); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + Walrus::Const32 *constant = reinterpret_cast(byteCode); + offsets[0] = constant->dstOffset(); + break; + } + default: { + i += byteCode->getSize(); + continue; + break; + } + } + + if (offsets[0] == SIZE_MAX && offsets[1] == SIZE_MAX && offsets[2] == SIZE_MAX && offsets[3] == SIZE_MAX) { + i += byteCode->getSize(); + continue; + } + + bool areLocals[] = { false, false, false, false }; + for (size_t j = m_currentFunctionType->param().size(); + j < m_localInfo.size(); j++) { + if (offsets[0] == m_localInfo[j].m_position) { + areLocals[0] = true; + } + if (offsets[1] == m_localInfo[j].m_position) { + areLocals[1] = true; + } + if (offsets[2] == m_localInfo[j].m_position) { + areLocals[2] = true; + } + if (offsets[3] == m_localInfo[j].m_position) { + areLocals[3] = true; + } + } + + if (areLocals[0] && areLocals[1] && areLocals[2] && areLocals[3]) { + i += byteCode->getSize(); + continue; + } + + if (!areLocals[0]) { + offsets[0] = SIZE_MAX; + } + if (!areLocals[1]) { + offsets[1] = SIZE_MAX; + } + if (!areLocals[2]) { + offsets[2] = SIZE_MAX; + } + if (!areLocals[3]) { + offsets[3] = SIZE_MAX; + } + + for (auto &range : variableRange) { + if (!(range.start <= i && range.end > i) || (range.start == 0 && range.end == SIZE_MAX)) { + continue; + } + + bool skip = false; + for (auto &info : infos) { + if (info.start == range.start && info.end == range.end) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + for (auto &offset : offsets) { + if (offset == SIZE_MAX) { + continue; + } + + bool alreadyAssigned = false; + for (auto &info : infos) { + if (info.originalPos == offset) { + alreadyAssigned = true; + } + } + + if (alreadyAssigned) { + continue; + } + + for (auto &info : infos) { + if (info.free && info.type == range.type) { + info.free = false; + info.originalPos = offset; + info.start = range.start; + info.end = range.end; + + if (info.firstPos == SIZE_MAX) { + info.firstPos = offset; + } + +#if !defined(NDEBUG) + info.assignedRanges.push_back({ range.start, range.end }); +#endif + break; + } + } + } + } + + for (size_t j = 0; j < infos.size(); j++) { + if (infos[j].originalPos == offsets[0] && offsets[0] != SIZE_MAX) { + switch (byteCode->opcode()) { + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::MoveI32 *move = reinterpret_cast(byteCode); + move->setDstOffset(infos[j].pos); + break; + } + case Walrus::ByteCode::GlobalGet32Opcode: + case Walrus::ByteCode::GlobalGet64Opcode: + case Walrus::ByteCode::GlobalGet128Opcode: { + Walrus::GlobalGet32 *get = reinterpret_cast(byteCode); + get->setDstOffset(infos[j].pos); + break; + } +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) +#undef GENERATE_BINARY_CODE_CASE + { + Walrus::BinaryOperation *binOp = reinterpret_cast(byteCode); + binOp->setDstOffset(infos[j].pos); + break; + } +#define GENERATE_UNARY_CODE_CASE(name, ...) case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_UNARY_OP_2(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_CONVERT_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OTHER(GENERATE_UNARY_CODE_CASE) +#undef GENERATE_UNARY_CODE_CASE + { + Walrus::UnaryOperation *unOp = reinterpret_cast(byteCode); + unOp->setDstOffset(infos[j].pos); + break; + } +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::I32Load *load = reinterpret_cast(byteCode); + load->setDstOffset(infos[j].pos); + break; + } +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + load->setDstOffset(infos[j].pos); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + load->setDstOffset(infos[j].pos); + break; + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setDstOffset(infos[j].pos); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + Walrus::Const32 *constant = reinterpret_cast(byteCode); + constant->setDstOffset(infos[j].pos); + break; + } + default: { + break; + } + } + } + + if (infos[j].originalPos == offsets[1] && offsets[1] != SIZE_MAX) { + switch (byteCode->opcode()) { +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) +#undef GENERATE_BINARY_CODE_CASE + { + Walrus::BinaryOperation *binOp = reinterpret_cast(byteCode); + binOp->setSrcOffset(infos[j].pos, 0); + break; + } +#define GENERATE_UNARY_CODE_CASE(name, ...) case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_UNARY_OP_2(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_CONVERT_OP(GENERATE_UNARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_UNARY_OTHER(GENERATE_UNARY_CODE_CASE) +#undef GENERATE_UNARY_CODE_CASE + { + Walrus::UnaryOperation *unOp = reinterpret_cast(byteCode); + unOp->setSrcOffset(infos[j].pos); + break; + } +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + load->setSrcOffset(infos[j].pos); + break; + } +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + { + Walrus::MemoryStore *store = reinterpret_cast(byteCode); + store->setSrc0Offset(infos[j].pos); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + load->setSrcOffset(infos[j].pos); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + store->setSrc0Offset(infos[j].pos); + break; + } + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::MoveI32 *move = reinterpret_cast(byteCode); + move->setSrcOffset(infos[j].pos); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setSrc0Offset(infos[j].pos); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + Walrus::Const32 *constant = reinterpret_cast(byteCode); + constant->setDstOffset(infos[j].pos); + break; + } + default: { + break; + } + } + } + + if (infos[j].originalPos == offsets[2] && offsets[2] != SIZE_MAX) { + switch (byteCode->opcode()) { +#define GENERATE_BINARY_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_SHIFT_OP(GENERATE_BINARY_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_BINARY_OTHER(GENERATE_BINARY_CODE_CASE) +#undef GENERATE_BINARY_CODE_CASE + { + Walrus::BinaryOperation *binOp = reinterpret_cast(byteCode); + binOp->setSrcOffset(infos[j].pos, 1); + break; + } +#define GENERATE_MEMORY_STORE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_STORE_OP(GENERATE_MEMORY_STORE_CODE_CASE) +#undef GENERATE_MEMORY_STORE_CODE_CASE + { + Walrus::MemoryStore *store = reinterpret_cast(byteCode); + store->setSrc1Offset(infos[j].pos); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + store->setSrc1Offset(infos[j].pos); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setSrc1Offset(infos[j].pos); + } + default: { + break; + } + } + } + if (infos[j].originalPos == offsets[3] && offsets[3] != SIZE_MAX) { + if (byteCode->opcode() == Walrus::ByteCode::SelectOpcode) { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setCondOffset(infos[j].pos); + } + } + } + + i += byteCode->getSize(); + } + + i = 0; + bool assigned = false; + Walrus::ByteCode *byteCode = reinterpret_cast(const_cast(m_currentFunction->byteCode())); + while (byteCode->opcode() == Walrus::ByteCode::Const32Opcode || byteCode->opcode() == Walrus::ByteCode::Const64Opcode || byteCode->opcode() == Walrus::ByteCode::Const128Opcode) { + assigned = false; + for (auto &info : infos) { + switch (byteCode->opcode()) { + case Walrus::ByteCode::Const32Opcode: { + if (info.originalPos == reinterpret_cast(byteCode)->dstOffset() && reinterpret_cast(byteCode)->value() == 0) { + reinterpret_cast(byteCode)->setDstOffset(info.pos); + assigned = true; + } + break; + } + case Walrus::ByteCode::Const64Opcode: { + if (info.originalPos == reinterpret_cast(byteCode)->dstOffset() && reinterpret_cast(byteCode)->value() == 0) { + reinterpret_cast(byteCode)->setDstOffset(info.pos); + assigned = true; + } + break; + } + case Walrus::ByteCode::Const128Opcode: { + if (info.originalPos == reinterpret_cast(byteCode)->dstOffset() && reinterpret_cast(byteCode)->value() == 0) { + reinterpret_cast(byteCode)->setDstOffset(info.pos); + assigned = true; + } + break; + } + default: { + RELEASE_ASSERT_NOT_REACHED(); + break; + } + } + + if (assigned) { + break; + } + } + + i += byteCode->getSize(); + byteCode = reinterpret_cast(const_cast(m_currentFunction->byteCode() + i)); + } + + for (size_t i = 0; i < infos.size(); i++) { + if (infos[i].originalPos != SIZE_MAX - 1) { + m_localInfo[i] = { infos[i].type, infos[i].pos }; + m_currentFunction->m_local[i] = infos[i].type; + } + + for (auto &end : ends) { + for (size_t j = 0; j < end->offsetsSize(); j++) { + if (end->resultOffsets()[j] == infos[i].originalPos) { + end->resultOffsets()[j] = infos[i].pos; + +#if defined(WALRUS_32) + if (infos[j].type == Walrus::Value::Type::F64) { + j++; + end->resultOffsets()[j] = infos[i].pos + 4; + } + if (infos[j].type == Walrus::Value::Type::V128) { + for (unsigned idx = 1; idx < 4; idx++) { + end->resultOffsets()[j + idx] = infos[i].pos + (idx * 4); + } + } +#else + if (infos[j].type == Walrus::Value::Type::V128) { + j++; + end->resultOffsets()[j] = infos[i].pos + 8; + } +#endif + } + } + } + } + +#if !defined(NDEBUG) + for (auto &range : variableRange) { + if (range.end != SIZE_MAX) { + m_currentFunction->m_variabeRange.push_back({ range.start, range.end }); + } + } + + m_currentFunction->m_localDebugData.clear(); + for (auto &info : infos) { + Walrus::ModuleFunction::LocalDebugInfo debugInfo; + debugInfo.stackPosition = info.pos; + + for (auto &range : info.assignedRanges) { + debugInfo.starts.push_back(range.first); + debugInfo.ends.push_back(range.second); + } + + m_currentFunction->m_localDebugData.push_back(debugInfo); + } + + for (size_t i = m_localInfo.size() - infos.size(); i > 0; i--) { + m_currentFunction->m_localDebugData.push_back( + Walrus::ModuleFunction::LocalDebugInfo{ SIZE_MAX, {}, {} }); + } +#endif + + m_optimizationCatchInfo.clear(); + // variable life analysis end + } }; } // namespace wabt namespace Walrus { - WASMParsingResult::WASMParsingResult() : m_seenStartAttribute(false) , m_version(0) @@ -2586,7 +3769,10 @@ void WASMParsingResult::clear() } } -std::pair, std::string> WASMParser::parseBinary(Store* store, const std::string& filename, const uint8_t* data, size_t len, const bool useJIT, const int jitVerbose) +std::pair, std::string> +WASMParser::parseBinary(Store *store, const std::string &filename, + const uint8_t *data, size_t len, const bool useJIT, + const int jitVerbose) { wabt::WASMBinaryReader delegate; @@ -2595,7 +3781,7 @@ std::pair, std::string> WASMParser::parseBinary(Store* store, return std::make_pair(nullptr, error); } - Module* module = new Module(store, delegate.parsingResult()); + Module *module = new Module(store, delegate.parsingResult()); if (useJIT) { module->jitCompile(nullptr, 0, jitVerbose); } diff --git a/src/runtime/Module.cpp b/src/runtime/Module.cpp index 0d3bbe9a3..4b89286b2 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -29,6 +29,7 @@ #include "interpreter/Interpreter.h" #include "parser/WASMParser.h" #include "wasi/WASI.h" +#include namespace Walrus { @@ -433,8 +434,18 @@ void ModuleFunction::dumpByteCode() pos += valueStackAllocatedSize(m_functionType->param()[i]); } for (size_t i = 0; i < m_local.size(); i++) { - printf("(local %zu, %s, pos %zu) ", i, typeName(m_local[i]), m_localDebugData[i]); + if (m_localDebugData[i].stackPosition == SIZE_MAX) { + printf("\n(local %zu, %s, optimized out)", i, typeName(m_local[i])); + } else { + printf("\n(local %zu, %s, pos %zu ", i, typeName(m_local[i]), m_localDebugData[i].stackPosition); + printf("ranges"); + for (size_t j = 0; j < m_localDebugData[i].starts.size(); j++) { + printf(" start %zu, end %zu", m_localDebugData[i].starts[j], m_localDebugData[i].ends[j]); + } + printf(")"); + } } + printf("\n"); for (size_t i = 0; i < m_constantDebugData.size(); i++) { printf("(constant "); dumpValue(m_constantDebugData[i].first); @@ -443,6 +454,13 @@ void ModuleFunction::dumpByteCode() printf("....]\n"); printf("bytecode size: %zu bytes\n", m_byteCode.size()); + + // printf("variable ranges: "); + // for (size_t j = 0; j < m_variabeRange.size(); j++) { + // printf("(range %zu ", j); + + // printf("start %u, end %u) ", m_variabeRange[j].first, m_variabeRange[j].second); + // } printf("\n"); size_t idx = 0; diff --git a/src/runtime/Module.h b/src/runtime/Module.h index 6f12c6453..a3ae2c14b 100644 --- a/src/runtime/Module.h +++ b/src/runtime/Module.h @@ -17,8 +17,10 @@ #ifndef __WalrusModule__ #define __WalrusModule__ +#include "Walrus.h" #include "runtime/ObjectType.h" #include "runtime/Object.h" +#include namespace wabt { class WASMBinaryReader; @@ -175,6 +177,14 @@ class ModuleFunction { uint32_t m_tagIndex; }; +#if !defined(NDEBUG) + struct LocalDebugInfo { + size_t stackPosition; + std::vector starts; + std::vector ends; + }; +#endif + ModuleFunction(FunctionType* functionType); ~ModuleFunction(); @@ -244,7 +254,8 @@ class ModuleFunction { ValueTypeVector m_local; Vector> m_byteCode; #if !defined(NDEBUG) - Vector> m_localDebugData; + Vector> m_variabeRange; + std::vector m_localDebugData; Vector, std::allocator>> m_constantDebugData; #endif Vector> m_catchInfo; diff --git a/test/basic/local_initialization.wast b/test/basic/local_initialization.wast new file mode 100644 index 000000000..3fc1ca869 --- /dev/null +++ b/test/basic/local_initialization.wast @@ -0,0 +1,63 @@ +(module + +;;(func (export "br_if_cmp")(param i32 i32 i64 f32 f64)(result i32 i32 i32 i32) +;; block (result i32) +;; i32.const -1 +;; local.get 0 +;; br_if 0 +;; drop +;; local.get 1 +;; i32.const 100 +;; i32.eq +;; end +;; block (result i32) +;; i32.const -1 +;; local.get 0 +;; br_if 0 +;; drop +;; local.get 2 +;; i64.const 100 +;; i64.eq +;; end +;; block (result i32) +;; i32.const -1 +;; local.get 0 +;; br_if 0 +;; drop +;; local.get 3 +;; f32.const 100.0 +;; f32.eq +;; end +;; block (result i32) +;; i32.const -1 +;; local.get 0 +;; br_if 0 +;; drop +;; local.get 4 +;; f64.const 100.0 +;; f64.eq +;; end +;;) + +(func (export "test10") (param i32) (result i32) + i32.const 6 + i32.const 7 + block (result i32) + local.get 0 + local.get 0 + i32.eqz + br_if 0 + + i32.const 5 + i32.le_s + end + select +) + +) + +(assert_return (invoke "test10" (i32.const 0) ) (i32.const 7) ) +;;(assert_return (invoke "br_if_cmp"(i32.const 0)(i32.const 100)(i64.const 100)(f32.const 100.0)(f64.const 100.0)) +;; (i32.const 1)(i32.const 1)(i32.const 1)(i32.const 1)) + + diff --git a/test/basic/local_livelyness.wast b/test/basic/local_livelyness.wast new file mode 100644 index 000000000..6f656ed8a --- /dev/null +++ b/test/basic/local_livelyness.wast @@ -0,0 +1,94 @@ +(module + (func $local_zero (export "local_zero")(result i32) + (local i32) + local.get 0 + ) + + (func $local_loop1 (export "local_loop1")(result i32) + (local i32 i32 i32) + i32.const 10 + local.set 0 ;;start of 0 + + ;;start of 1 + (loop $loop + i32.const 1 + local.set 1 ;;start of 1, but inside loop + + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + i32.eqz + br_if $loop + ) + + local.get 1 ;;end of 1 + ) + + (func $local_blocks (export "local_block1")(result i32) + (local i32 i32 i32 i32 i64) + + ;;end of 2 + + local.get 4 ;; start of 4 + local.get 3 ;; start of 3 + drop + drop + + i32.const 0 + local.set 0 ;; start of 0 + + + (block $block1 + i32.const 1 + local.get 0 + i32.add + local.set 0 + + (loop $block2 + local.get 1 ;; start of 1 + i32.const 3 + i32.eq + br_if $block2 + ) + + i32.const 0 + local.get 1 + i32.add + drop + ) ;; end of 1 + + ;; end of 3, 4 + i32.const 0 + ) + + (func $local_blocks2 (export "local_block2")(param i32)(result i32) + (local i32) + + i32.const 1 + i32.const 1 + i32.sub + drop + + local.get 0 + local.tee 1 + ) + + (func $params (export "params")(param i32 i64 i32 v128)(result i32) + (local i32 i64 v128) + i32.const 0 + ) + + (func $params2 (export "params2")(param v128 i32 v128)(result i32) + i32.const 0 + ) + + +) + +(assert_return (invoke "local_zero") (i32.const 0)) +(assert_return (invoke "local_loop1") (i32.const 1)) +(assert_return (invoke "local_block1") (i32.const 0)) +(assert_return (invoke "local_block2" (i32.const 42)) (i32.const 42)) +(assert_return (invoke "params" (i32.const 1) (i64.const 2) (i32.const 3) (v128.const i64x2 4 5)) (i32.const 0)) +(assert_return (invoke "params2" (v128.const i64x2 1 2) (i32.const 3) (v128.const i64x2 4 5)) (i32.const 0)) diff --git a/test/basic/local_sets.wast b/test/basic/local_sets.wast new file mode 100644 index 000000000..afd4f986e --- /dev/null +++ b/test/basic/local_sets.wast @@ -0,0 +1,110 @@ +(module + (;(func $test (export "test")(param i32)(result i32) + (local i32 i32 i32 i64) + + local.get 0 ;; start of 0 + local.get 1 ;; start of 1 + drop + drop + + i32.const 32 + local.set 0 + + i32.const 33 + local.set 1 + + local.get 0 + local.get 1 ;; end of 1 + drop + drop + + i32.const 34 + local.set 0 ;; end of 0 + + + i32.const 1 + local.set 2 ;; start of 2 + local.get 2 ;; end of 2 + drop + + i64.const 23 + local.set 4 + local.get 4 + drop + + i32.const 0 + ) + ;) + + + (func $test2 (export "test2")(result i32) + (local i32 i32 i32 i32 i32) + + i32.const 10 + local.set 0 + (loop $outer ;; runs 10 times + + i32.const 5 + local.set 1 + (loop $inner1 ;; runs 5 times + i32.const 42 + local.set 2 + local.get 2 + drop + + local.get 1 + i32.const 1 + i32.sub + local.tee 1 + + i32.const 0 + i32.eq + br_if $inner1 + ) + + i32.const 8 + local.set 3 + (loop $inner2 ;; runs 8 times + local.get 3 + i32.const 1 + i32.sub + local.tee 3 + + i32.const 0 + i32.eq + br_if $inner2 + ) + + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + + i32.const 0 + i32.eq + br_if $outer + ) + + (block $block + i32.const 99999 + local.set 4 + + i32.const 0 + i32.eqz + br_if $block + local.get 4 + + ;;junk + i32.const 0 + i32.add + i32.eqz + i32.clz + drop + ) + + i32.const 0 + ) +) + +;;(assert_return (invoke "test" (i32.const 12))(i32.const 0)) +(assert_return (invoke "test2")(i32.const 0)) diff --git a/test/basic/useless_locals.wast b/test/basic/useless_locals.wast new file mode 100644 index 000000000..a96b64083 --- /dev/null +++ b/test/basic/useless_locals.wast @@ -0,0 +1,8 @@ +(module + (func $useless_locals (export "useless_locals")(param i32)(result i32) + (local i32 i32) + i32.const 42 + ) +) + +(assert_return (invoke "useless_locals" (i32.const 222)) (i32.const 42))