diff --git a/src/interpreter/ByteCode.h b/src/interpreter/ByteCode.h index b80f98b6f..92d8d68b6 100644 --- a/src/interpreter/ByteCode.h +++ b/src/interpreter/ByteCode.h @@ -767,6 +767,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) { @@ -809,6 +810,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) { @@ -860,7 +869,9 @@ class Move : 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; } protected: ByteCodeStackOffset m_srcOffset; @@ -1015,7 +1026,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) @@ -1067,7 +1080,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) @@ -1144,6 +1159,7 @@ class JumpIfTrue : public ByteCode { } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } + void setSrcOffset(ByteCodeStackOffset o) { m_srcOffset = o; } int32_t offset() const { return m_offset; } void setOffset(int32_t offset) { @@ -1174,6 +1190,7 @@ class JumpIfFalse : public ByteCode { } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } + void setSrcOffset(ByteCodeStackOffset o) { m_srcOffset = o; } int32_t offset() const { return m_offset; } void setOffset(int32_t offset) { @@ -1208,11 +1225,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) @@ -1245,6 +1266,7 @@ class BrTable : public ByteCode { } ByteCodeStackOffset condOffset() const { return m_condOffset; } + void setCondOffset(ByteCodeStackOffset o) { m_condOffset = o; } int32_t defaultOffset() const { return m_defaultOffset; } static inline size_t offsetOfDefault() { return offsetof(BrTable, m_defaultOffset); } @@ -1283,6 +1305,7 @@ class MemorySize : public ByteCode { } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1315,6 +1338,10 @@ class MemoryInit : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } #if !defined(NDEBUG) void dump(size_t pos) @@ -1346,6 +1373,10 @@ class MemoryCopy : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } #if !defined(NDEBUG) void dump(size_t pos) @@ -1373,6 +1404,10 @@ class MemoryFill : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } #if !defined(NDEBUG) void dump(size_t pos) @@ -1423,7 +1458,9 @@ class MemoryGrow : 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) @@ -1452,7 +1489,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) @@ -1481,8 +1520,11 @@ class SIMDMemoryLoad : public ByteCode { uint32_t offset() const { return m_offset; } ByteCodeStackOffset index() const { return m_index; } 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) @@ -1550,7 +1592,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) @@ -1577,8 +1621,11 @@ class SIMDMemoryStore : public ByteCode { uint32_t offset() const { return m_offset; } ByteCodeStackOffset index() const { return m_index; } + void setIndex(ByteCodeStackOffset o) { m_index = o; } 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) @@ -1604,8 +1651,11 @@ class SIMDExtractLane : public ByteCode { } ByteCodeStackOffset index() const { return m_index; } + void setIndex(ByteCodeStackOffset o) { m_index = o; } 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) @@ -1631,7 +1681,9 @@ class SIMDReplaceLane : public ByteCode { uint32_t index() const { return m_index; } const ByteCodeStackOffset* srcOffsets() const { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) { m_srcOffsets[idx] = o; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -1954,7 +2006,12 @@ class V128BitSelect : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -2010,7 +2067,9 @@ class I8X16Shuffle : public ByteCode { } const ByteCodeStackOffset* srcOffsets() const { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) { m_srcOffsets[idx] = o; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } const uint8_t* value() const { return m_value; } #if !defined(NDEBUG) @@ -2037,7 +2096,9 @@ class TableGet : public ByteCode { uint32_t tableIndex() const { return m_tableIndex; } 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) @@ -2066,7 +2127,9 @@ class TableSet : 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; } uint32_t tableIndex() const { return m_tableIndex; } #if !defined(NDEBUG) @@ -2098,8 +2161,11 @@ class TableGrow : public ByteCode { uint32_t tableIndex() const { return m_tableIndex; } 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) @@ -2130,6 +2196,7 @@ class TableSize : public ByteCode { uint32_t tableIndex() const { return m_tableIndex; } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } #if !defined(NDEBUG) void dump(size_t pos) @@ -2161,6 +2228,10 @@ class TableCopy : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } #if !defined(NDEBUG) void dump(size_t pos) @@ -2193,6 +2264,11 @@ class TableFill : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } + #if !defined(NDEBUG) void dump(size_t pos) { @@ -2225,6 +2301,11 @@ class TableInit : public ByteCode { { return m_srcOffsets; } + void setSrcOffset(ByteCodeStackOffset o, size_t idx) + { + m_srcOffsets[idx] = o; + } + #if !defined(NDEBUG) void dump(size_t pos) { @@ -2276,6 +2357,7 @@ class RefFunc : public ByteCode { } ByteCodeStackOffset dstOffset() const { return m_dstOffset; } + void setDstOffset(ByteCodeStackOffset o) { m_dstOffset = o; } uint32_t funcIndex() const { return m_funcIndex; } #if !defined(NDEBUG) @@ -2302,6 +2384,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) @@ -2382,6 +2465,7 @@ class GlobalSet32 : public ByteCode { { } + void setSrcOffset(ByteCodeStackOffset o) { m_srcOffset = o; } ByteCodeStackOffset srcOffset() const { return m_srcOffset; } uint32_t index() const { return m_index; } diff --git a/src/parser/WASMParser.cpp b/src/parser/WASMParser.cpp index d7114559c..390d790c6 100644 --- a/src/parser/WASMParser.cpp +++ b/src/parser/WASMParser.cpp @@ -43,7 +43,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 +151,64 @@ static Walrus::SegmentMode toSegmentMode(uint8_t flags) class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { private: + struct block { + enum blockType { + forwards, + backwards, + tryCatch, + }; + + size_t start; + size_t end; + blockType jumpType; + + + block(size_t jumpPos, size_t target) + { + if (jumpPos < target) { + jumpType = forwards; + start = jumpPos; + end = target; + } else { + jumpType = backwards; + start = target; + end = jumpPos; + } + } + }; + + struct variableRangeInfo { + enum blockRelation { + None, + Partial, + Full, + }; + + Walrus::ByteCodeStackOffset originalPosition; + bool needsInit; + Walrus::Value::Type type; + size_t start; + size_t end; + std::vector sets; + std::vector gets; + std::vector> blocksWithRelation; + }; + + struct variableInfo { + Walrus::Value::Type type; + bool free; + Walrus::ByteCodeStackOffset pos; + std::vector originalPositions; + Walrus::ByteCodeStackOffset firstPos; + size_t start; + size_t end; + + std::vector assignedRanges; + }; + 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 +217,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) @@ -175,7 +230,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - const VMStackInfo& operator=(const VMStackInfo& src) + const VMStackInfo &operator=(const VMStackInfo &src) { m_valueType = src.m_valueType; m_position = src.m_position; @@ -225,7 +280,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } 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,7 +317,7 @@ 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) @@ -274,7 +329,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { 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) { @@ -306,8 +361,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_codeEndOffset; struct PreprocessData { @@ -337,7 +392,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { std::vector m_usageInfo; }; - PreprocessData(WASMBinaryReader& reader) + PreprocessData(WASMBinaryReader &reader) : m_inPreprocess(false) , m_reader(reader) { @@ -356,7 +411,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(); } } @@ -367,7 +422,7 @@ 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++; } @@ -376,7 +431,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (!m_localVariableInfo[localIndex].m_needsExplicitInitOnStartup) { 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; @@ -421,7 +476,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - void addConstantData(const Walrus::Value& v) + void addConstantData(const Walrus::Value &v) { if (m_inPreprocess) { bool found = false; @@ -450,7 +505,7 @@ 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; }); } @@ -461,15 +516,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } 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; @@ -497,24 +552,26 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { Walrus::Vector> m_memoryInitData; uint32_t m_elementTableIndex; - Walrus::Optional m_elementOffsetFunction; - Walrus::Vector m_elementExprFunctions; + Walrus::Optional m_elementOffsetFunction; + Walrus::Vector m_elementExprFunctions; Walrus::SegmentMode m_segmentMode; Walrus::WASMParsingResult m_result; PreprocessData m_preprocessData; + std::vector> m_stackValues; + // i32.eqz and JumpIf can be unified in some cases 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; } @@ -537,6 +594,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // FIXME too many stack usage. we could not support this(yet) ASSERT(m_functionStackSizeSoFar + allocSize <= std::numeric_limits::max()); + if (localIndex == SIZE_MAX) { + m_stackValues.push_back({ type, pos }); + } + m_functionStackSizeSoFar += allocSize; m_currentFunction->m_requiredStackSize = std::max( m_currentFunction->m_requiredStackSize, m_functionStackSizeSoFar); @@ -570,7 +631,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 @@ -593,7 +654,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; @@ -612,6 +673,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { void endFunction() { + optimizeLocals(); m_currentFunction = nullptr; m_currentFunctionType = nullptr; m_vmStack.clear(); @@ -619,12 +681,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); @@ -638,7 +700,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { * * 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); } @@ -702,8 +764,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,16 +781,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnFuncType(Index index, Index paramCount, - Type* paramTypes, + Type *paramTypes, Index resultCount, - Type* resultTypes) override + 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])); } @@ -749,7 +811,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { ASSERT(m_result.m_functions.size() == funcIndex); ASSERT(m_result.m_imports.size() == importIndex); - Walrus::FunctionType* ft = m_result.m_functionTypes[sigIndex]; + 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( @@ -911,7 +973,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - 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); @@ -952,7 +1014,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void BeginGlobalInitExpr(Index index) override { auto ft = Walrus::Store::getDefaultFunctionType(m_result.m_globalTypes[index]->type()); - Walrus::ModuleFunction* mf = new Walrus::ModuleFunction(ft); + Walrus::ModuleFunction *mf = new Walrus::ModuleFunction(ft); m_result.m_globalTypes[index]->setFunction(mf); beginFunction(mf, true); } @@ -1056,10 +1118,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // 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(); - // put already aligned variables first + // 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]; + 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,7 +1137,7 @@ 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]; + 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); @@ -1098,31 +1160,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_functionStackSizeSoFar = m_initialFunctionStackSize; 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) { - 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); - } else if (size == 8) { - pushByteCode(Walrus::Const64(localPos, 0), WASMOpcode::I64ConstOpcode); - } else { - ASSERT(size == 16); - uint8_t empty[16] = { - 0, - }; - pushByteCode(Walrus::Const128(localPos, empty), WASMOpcode::V128ConstOpcode); - } - } -#if !defined(NDEBUG) - m_currentFunction->m_localDebugData.push_back(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); @@ -1130,9 +1170,9 @@ 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); @@ -1147,7 +1187,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - uint16_t computeFunctionParameterOrResultOffsetCount(const Walrus::ValueTypeVector& types) + uint16_t computeFunctionParameterOrResultOffsetCount(const Walrus::ValueTypeVector &types) { uint16_t result = 0; for (auto t : types) { @@ -1157,8 +1197,8 @@ 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(); @@ -1196,7 +1236,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); auto code = m_currentFunction->peekByteCode(callPos); generateCallExpr(code, parameterCount, resultCount, functionType); @@ -1212,13 +1252,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); + 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); @@ -1237,7 +1277,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); @@ -1245,7 +1285,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); @@ -1253,7 +1293,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); @@ -1261,13 +1301,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); } - virtual void OnV128ConstExpr(uint8_t* value) override + virtual void OnV128ConstExpr(uint8_t *value) override { if (processConstValue(Walrus::Value(Walrus::Value::Type::V128, value))) { return; @@ -1299,7 +1339,7 @@ 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; @@ -1438,7 +1478,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(); @@ -1451,19 +1491,19 @@ 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(); @@ -1485,7 +1525,7 @@ 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); @@ -1514,7 +1554,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(); @@ -1533,7 +1573,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 { @@ -1566,7 +1606,7 @@ 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]); } @@ -1672,10 +1712,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto offsetCount = computeFunctionParameterOrResultOffsetCount(m_currentFunctionType->result()); pushByteCode(Walrus::End(offsetCount), WASMOpcode::EndOpcode); - auto& result = m_currentFunctionType->result(); + 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); + 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]; @@ -1729,7 +1769,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) { @@ -1738,7 +1778,7 @@ 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; @@ -1786,7 +1826,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (dropSize.second) { size_t pos = m_currentFunction->currentByteCodeSize(); @@ -1817,7 +1857,7 @@ 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; @@ -1861,7 +1901,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; } @@ -1869,12 +1909,12 @@ 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); @@ -1884,10 +1924,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); @@ -1898,7 +1938,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (numTargets) { m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(int32_t) * numTargets)); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + 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)); @@ -1910,7 +1950,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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); @@ -1938,10 +1978,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; - auto& param = functionType->param(); + 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); + 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(); } @@ -1966,7 +2006,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); @@ -2405,13 +2445,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]); } @@ -2432,7 +2472,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { 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; } @@ -2585,7 +2625,7 @@ 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); @@ -2693,7 +2733,1882 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - Walrus::WASMParsingResult& parsingResult() { return m_result; } + Walrus::WASMParsingResult &parsingResult() { return m_result; } + + size_t arrayOffsetFromValue(Walrus::Value::Type type) + { +#if defined(WALRUS_32) + switch (type) { + case Walrus::Value::I32: + case Walrus::Value::F32: + case Walrus::Value::FuncRef: { + return 1; + } + case Walrus::Value::I64: + case Walrus::Value::F64: { + return 2; + } + case Walrus::Value::V128: { + return 4; + } + default: { + break; + } + } +#else + switch (type) { + case Walrus::Value::I32: + case Walrus::Value::F32: + case Walrus::Value::FuncRef: + case Walrus::Value::I64: + case Walrus::Value::F64: { + return 1; + } + case Walrus::Value::V128: { + return 2; + } + default: { + break; + } + } +#endif + return 0; + } + + + void setByteCodeDestination(Walrus::ByteCode *byteCode, Walrus::ByteCodeStackOffset position) + { + switch (byteCode->opcode()) { + case Walrus::ByteCode::I64ReinterpretF64Opcode: + case Walrus::ByteCode::F32ReinterpretI32Opcode: + case Walrus::ByteCode::F64ReinterpretI64Opcode: + case Walrus::ByteCode::I32ReinterpretF32Opcode: + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::Move *move = reinterpret_cast(byteCode); + move->setDstOffset(position); + break; + } + case Walrus::ByteCode::GlobalGet32Opcode: + case Walrus::ByteCode::GlobalGet64Opcode: + case Walrus::ByteCode::GlobalGet128Opcode: { + Walrus::GlobalGet32 *get = reinterpret_cast(byteCode); + get->setDstOffset(position); + 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(position); + 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(position); + break; + } + case Walrus::ByteCode::V128Load32ZeroOpcode: + case Walrus::ByteCode::V128Load64ZeroOpcode: +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_EXTEND_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + load->setDstOffset(position); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + load->setDstOffset(position); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setDstOffset(position); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + Walrus::Const32 *constant = reinterpret_cast(byteCode); + constant->setDstOffset(position); + break; + } + case Walrus::ByteCode::MemorySizeOpcode: { + Walrus::MemorySize *memSize = reinterpret_cast(byteCode); + memSize->setDstOffset(position); + break; + } + case Walrus::ByteCode::MemoryGrowOpcode: { + Walrus::MemoryGrow *memGrow = reinterpret_cast(byteCode); + memGrow->setDstOffset(position); + break; + } + case Walrus::ByteCode::TableGetOpcode: { + Walrus::TableGet *tableGet = reinterpret_cast(byteCode); + tableGet->setDstOffset(position); + break; + } + case Walrus::ByteCode::TableGrowOpcode: { + Walrus::TableGrow *tableGrow = reinterpret_cast(byteCode); + tableGrow->setDstOffset(position); + break; + } + case Walrus::ByteCode::TableSizeOpcode: { + Walrus::TableSize *tableSize = reinterpret_cast(byteCode); + tableSize->setDstOffset(position); + break; + } + case Walrus::ByteCode::RefFuncOpcode: { + Walrus::RefFunc *refFunc = reinterpret_cast(byteCode); + refFunc->setDstOffset(position); + break; + } + case Walrus::ByteCode::I8X16ShuffleOpcode: { + Walrus::I8X16Shuffle *simdShuffle = reinterpret_cast(byteCode); + simdShuffle->setDstOffset(position); + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + Walrus::V128BitSelect *select = reinterpret_cast(byteCode); + select->setDstOffset(position); + break; + } +#define GENERATE_SIMD_MEMORY_LOAD_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_SIMD_MEMORY_LOAD_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CODE_CASE + { + Walrus::SIMDMemoryLoad *load = reinterpret_cast(byteCode); + load->setDstOffset(position); + break; + } +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE + { + Walrus::SIMDReplaceLane *lane = reinterpret_cast(byteCode); + lane->setDstOffset(position); + break; + } +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) +#undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE + { + Walrus::SIMDExtractLane *lane = reinterpret_cast(byteCode); + lane->setDstOffset(position); + break; + } + default: { + break; + } + } + } + + void setByteCodeSrc0(Walrus::ByteCode *byteCode, Walrus::ByteCodeStackOffset position) + { + 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(position, 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(position); + break; + } + case Walrus::ByteCode::V128Load32ZeroOpcode: + case Walrus::ByteCode::V128Load64ZeroOpcode: +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_EXTEND_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + load->setSrcOffset(position); + 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(position); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + load->setSrcOffset(position); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + store->setSrc0Offset(position); + break; + } + case Walrus::ByteCode::I64ReinterpretF64Opcode: + case Walrus::ByteCode::F32ReinterpretI32Opcode: + case Walrus::ByteCode::F64ReinterpretI64Opcode: + case Walrus::ByteCode::I32ReinterpretF32Opcode: + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::Move *move = reinterpret_cast(byteCode); + move->setSrcOffset(position); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setSrc0Offset(position); + break; + } + case Walrus::ByteCode::GlobalSet32Opcode: + case Walrus::ByteCode::GlobalSet64Opcode: + case Walrus::ByteCode::GlobalSet128Opcode: { + Walrus::GlobalSet32 *globalSet = reinterpret_cast(byteCode); + globalSet->setSrcOffset(position); + break; + } + case Walrus::ByteCode::JumpIfTrueOpcode: + case Walrus::ByteCode::JumpIfFalseOpcode: { + reinterpret_cast(byteCode)->setSrcOffset(position); + break; + } + case Walrus::ByteCode::MemoryGrowOpcode: { + Walrus::MemoryGrow *memGrow = reinterpret_cast(byteCode); + memGrow->setSrcOffset(position); + break; + } + case Walrus::ByteCode::MemoryInitOpcode: { + Walrus::MemoryInit *memInit = reinterpret_cast(byteCode); + memInit->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::MemoryCopyOpcode: { + Walrus::MemoryCopy *memCopy = reinterpret_cast(byteCode); + memCopy->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::MemoryFillOpcode: { + Walrus::MemoryFill *memFill = reinterpret_cast(byteCode); + memFill->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::TableGetOpcode: { + Walrus::TableGet *tableGet = reinterpret_cast(byteCode); + tableGet->setSrcOffset(position); + break; + } + case Walrus::ByteCode::TableSetOpcode: { + Walrus::TableSet *tableSet = reinterpret_cast(byteCode); + tableSet->setSrc0Offset(position); + break; + } + case Walrus::ByteCode::TableGrowOpcode: { + Walrus::TableGrow *tableGrow = reinterpret_cast(byteCode); + tableGrow->setSrc0Offset(position); + break; + } + case Walrus::ByteCode::TableCopyOpcode: { + Walrus::TableCopy *tableCopy = reinterpret_cast(byteCode); + tableCopy->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::TableFillOpcode: { + Walrus::TableFill *tableFill = reinterpret_cast(byteCode); + tableFill->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::TableInitOpcode: { + Walrus::TableInit *tableInit = reinterpret_cast(byteCode); + tableInit->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::I8X16ShuffleOpcode: { + Walrus::I8X16Shuffle *simdShuffle = reinterpret_cast(byteCode); + simdShuffle->setSrcOffset(position, 0); + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + Walrus::V128BitSelect *select = reinterpret_cast(byteCode); + select->setSrcOffset(position, 0); + break; + } +#define GENERATE_SIMD_MEMORY_LOAD_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_SIMD_MEMORY_LOAD_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CODE_CASE + { + Walrus::SIMDMemoryLoad *load = reinterpret_cast(byteCode); + load->setSrc0Offset(position); + break; + } +#define GENERATE_SIMD_MEMORY_STORE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_SIMD_MEMORY_STORE_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CASE + { + Walrus::SIMDMemoryStore *store = reinterpret_cast(byteCode); + store->setSrc0Offset(position); + break; + } +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE + { + Walrus::SIMDReplaceLane *lane = reinterpret_cast(byteCode); + lane->setSrcOffset(position, 0); + break; + } +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) +#undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE + { + Walrus::SIMDExtractLane *lane = reinterpret_cast(byteCode); + lane->setSrcOffset(position); + break; + } + default: { + break; + } + } + } + + void setByteCodeSrc1(Walrus::ByteCode *byteCode, Walrus::ByteCodeStackOffset position) + { + 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(position, 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(position); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + store->setSrc1Offset(position); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setSrc1Offset(position); + break; + } + case Walrus::ByteCode::MemoryInitOpcode: { + Walrus::MemoryInit *memInit = reinterpret_cast(byteCode); + memInit->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::MemoryCopyOpcode: { + Walrus::MemoryCopy *memCopy = reinterpret_cast(byteCode); + memCopy->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::MemoryFillOpcode: { + Walrus::MemoryFill *memFill = reinterpret_cast(byteCode); + memFill->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::TableSetOpcode: { + Walrus::TableSet *tableSet = reinterpret_cast(byteCode); + tableSet->setSrc1Offset(position); + break; + } + case Walrus::ByteCode::TableGrowOpcode: { + Walrus::TableGrow *tableGrow = reinterpret_cast(byteCode); + tableGrow->setSrc1Offset(position); + break; + } + case Walrus::ByteCode::TableCopyOpcode: { + Walrus::TableCopy *tableCopy = reinterpret_cast(byteCode); + tableCopy->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::TableFillOpcode: { + Walrus::TableFill *tableFill = reinterpret_cast(byteCode); + tableFill->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::TableInitOpcode: { + Walrus::TableInit *tableInit = reinterpret_cast(byteCode); + tableInit->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::I8X16ShuffleOpcode: { + Walrus::I8X16Shuffle *simdShuffle = reinterpret_cast(byteCode); + simdShuffle->setSrcOffset(position, 1); + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + Walrus::V128BitSelect *select = reinterpret_cast(byteCode); + select->setSrcOffset(position, 1); + break; + } +#define GENERATE_SIMD_MEMORY_LOAD_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_SIMD_MEMORY_LOAD_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CASE + { + Walrus::SIMDMemoryLoad *load = reinterpret_cast(byteCode); + load->setSrc1Offset(position); + break; + } +#define GENERATE_SIMD_MEMORY_STORE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_SIMD_MEMORY_STORE_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CASE + { + Walrus::SIMDMemoryStore *store = reinterpret_cast(byteCode); + store->setSrc1Offset(position); + break; + } +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE + { + Walrus::SIMDReplaceLane *lane = reinterpret_cast(byteCode); + lane->setSrcOffset(position, 1); + break; + } + default: { + break; + } + } + } + + void setByteCodeExtra(Walrus::ByteCode *byteCode, Walrus::ByteCodeStackOffset position) + { + switch (byteCode->opcode()) { + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + select->setCondOffset(position); + break; + } + case Walrus::ByteCode::MemoryInitOpcode: { + Walrus::MemoryInit *memInit = reinterpret_cast(byteCode); + memInit->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::MemoryCopyOpcode: { + Walrus::MemoryCopy *memCopy = reinterpret_cast(byteCode); + memCopy->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::MemoryFillOpcode: { + Walrus::MemoryFill *memFill = reinterpret_cast(byteCode); + memFill->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::TableCopyOpcode: { + Walrus::TableCopy *tableCopy = reinterpret_cast(byteCode); + tableCopy->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::TableFillOpcode: { + Walrus::TableFill *tableFill = reinterpret_cast(byteCode); + tableFill->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::TableInitOpcode: { + Walrus::TableInit *tableInit = reinterpret_cast(byteCode); + tableInit->setSrcOffset(position, 2); + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + Walrus::V128BitSelect *select = reinterpret_cast(byteCode); + select->setSrcOffset(position, 2); + break; + } + default: { + break; + } + } + } + + void optimizeLocals() + { + if (m_currentFunction->functionType()->param().size() == m_localInfo.size()) { + return; + } + + // first = target of jump, second = the information of the block + std::vector blocks; + std::vector variableRange; + std::vector ends; + std::vector calls; + std::vector brTables; + std::vector throws; + + size_t variableSize = m_localInfo.size(); + size_t paramSize = m_currentFunctionType->param().size(); + for (unsigned i = paramSize; i < variableSize; i++) { + variableRange.push_back({ (uint16_t)m_localInfo[i].m_position, false, m_localInfo[i].m_valueType, SIZE_MAX, 0, {}, {}, {} }); + } + + size_t i = 0; + + // information collection and naive range finding + 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, SIZE_MAX }; + std::vector callOffsets = {}; + + 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::I64ReinterpretF64Opcode: + case Walrus::ByteCode::F32ReinterpretI32Opcode: + case Walrus::ByteCode::F64ReinterpretI64Opcode: + case Walrus::ByteCode::I32ReinterpretF32Opcode: + 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::GlobalSet32Opcode: + case Walrus::ByteCode::GlobalSet64Opcode: + case Walrus::ByteCode::GlobalSet128Opcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + 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; + } + case Walrus::ByteCode::V128Load32ZeroOpcode: + case Walrus::ByteCode::V128Load64ZeroOpcode: +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_EXTEND_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_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_SIMD_MEMORY_LOAD_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_SIMD_MEMORY_LOAD_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_CASE + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + 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; + } +#define GENERATE_SIMD_MEMORY_STORE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_SIMD_MEMORY_STORE_CASE) +#undef GENERATE_SIMD_MEMORY_STORE_CASE + { + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) +#undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE + { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + break; + } + case Walrus::ByteCode::SelectOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + offsets[3] = reinterpret_cast(byteCode)->condOffset(); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::MemorySizeOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::MemoryGrowOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } + case Walrus::ByteCode::MemoryInitOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::MemoryCopyOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::MemoryFillOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::RefFuncOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::TableSizeOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + break; + } + case Walrus::ByteCode::TableGrowOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } + case Walrus::ByteCode::TableGetOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + break; + } + case Walrus::ByteCode::TableSetOpcode: { + offsets[1] = reinterpret_cast(byteCode)->src0Offset(); + offsets[2] = reinterpret_cast(byteCode)->src1Offset(); + break; + } + case Walrus::ByteCode::TableInitOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::TableCopyOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::TableFillOpcode: { + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + break; + } + case Walrus::ByteCode::I8X16ShuffleOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + offsets[0] = reinterpret_cast(byteCode)->dstOffset(); + offsets[1] = reinterpret_cast(byteCode)->srcOffsets()[0]; + offsets[2] = reinterpret_cast(byteCode)->srcOffsets()[1]; + offsets[3] = reinterpret_cast(byteCode)->srcOffsets()[2]; + 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: { + offsets[1] = reinterpret_cast(byteCode)->srcOffset(); + jumpOffset = (size_t)std::abs((int64_t)(i + reinterpret_cast(byteCode)->offset())); + break; + } + case Walrus::ByteCode::EndOpcode: { + ends.push_back(reinterpret_cast(byteCode)); + + Walrus::End *end = reinterpret_cast(byteCode); + size_t offset = 0; + for (size_t j = 0; j < m_currentFunctionType->result().size(); j++) { + for (size_t k = 0; k < m_localInfo.size() - paramSize; k++) { + if (end->resultOffsets()[offset] == m_localInfo[k].m_position) { + variableRange[k].gets.push_back(i); + variableRange[k].end = i; + } + offset += arrayOffsetFromValue(m_currentFunctionType->result()[j]); + } + } + + break; + } + case Walrus::ByteCode::CallOpcode: { + calls.push_back(byteCode); + + Walrus::Call *call = reinterpret_cast(byteCode); + Walrus::ModuleFunction *target = m_result.m_functions[call->index()]; + + size_t offset = 0; + for (size_t j = 0; j < target->m_functionType->param().size(); j++) { + callOffsets.push_back(call->stackOffsets()[offset]); + offset += arrayOffsetFromValue(target->m_functionType->param()[j]); + } + + for (size_t j = 0; j < target->m_functionType->result().size(); j++) { + callOffsets.push_back(call->stackOffsets()[offset]); + offset += arrayOffsetFromValue(target->m_functionType->result()[j]); + } + break; + } + case Walrus::ByteCode::CallIndirectOpcode: { + calls.push_back(byteCode); + Walrus::CallIndirect *call = reinterpret_cast(byteCode); + + size_t offset = 0; + for (size_t j = 0; j < call->functionType()->param().size(); j++) { + callOffsets.push_back(call->stackOffsets()[offset]); + offset += arrayOffsetFromValue(call->functionType()->param()[j]); + } + + for (size_t j = 0; j < call->functionType()->result().size(); j++) { + callOffsets.push_back(call->stackOffsets()[offset]); + offset += arrayOffsetFromValue(call->functionType()->result()[j]); + } + break; + } + case Walrus::ByteCode::BrTableOpcode: { + Walrus::BrTable *brTable = reinterpret_cast(byteCode); + brTables.push_back(brTable); + + for (size_t j = 0; j < brTable->tableSize(); j++) { + int32_t o = brTable->jumpOffsets()[j]; + blocks.push_back({ i, o < 0 ? i + o : i - o }); + } + + break; + } + case Walrus::ByteCode::ThrowOpcode: { + throws.push_back(reinterpret_cast(byteCode)); + break; + } + default: { + i += byteCode->getSize(); + continue; + } + } + + for (size_t j = 0; j < variableRange.size(); j++) { + if (offsets[0] == SIZE_MAX && offsets[1] == SIZE_MAX && offsets[2] == SIZE_MAX && offsets[3] == SIZE_MAX) { + break; + } + + if (m_localInfo[paramSize + j].m_position == offsets[0] + || m_localInfo[paramSize + j].m_position == offsets[1] + || m_localInfo[paramSize + j].m_position == offsets[2] + || m_localInfo[paramSize + j].m_position == offsets[3]) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + variableRange[j].end = i; + } + + if (m_localInfo[paramSize + j].m_position == offsets[0]) { + variableRange[j].sets.push_back(i); + } + + if (m_localInfo[paramSize + j].m_position == offsets[1] + || m_localInfo[paramSize + j].m_position == offsets[2] + || m_localInfo[paramSize + j].m_position == offsets[3]) { + variableRange[j].gets.push_back(i); + } + } + + for (size_t j = 0; j < variableRange.size(); j++) { + for (size_t callOffset : callOffsets) { + if (m_localInfo[paramSize + j].m_position == callOffset) { + if (variableRange[j].end < i) { + variableRange[j].end = i; + } + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + variableRange[j].gets.push_back(i); + } + } + + for (auto &end : ends) { + for (size_t count = 0; count < end->offsetsSize(); count++) { + if (m_localInfo[paramSize + j].m_position == end->resultOffsets()[count]) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + if (variableRange[j].end < i) { + variableRange[j].end = m_currentFunction->currentByteCodeSize(); + } + variableRange[j].gets.push_back(i); + } + } + } + + for (auto &brTable : brTables) { + if (m_localInfo[paramSize + j].m_position == brTable->condOffset()) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + if (variableRange[j].end < i) { + variableRange[j].end = i; + } + variableRange[j].gets.push_back(i); + } + } + + for (auto &throwCode : throws) { + for (size_t count = 0; count < throwCode->offsetsSize(); count++) { + if (m_localInfo[paramSize + j].m_position == throwCode->dataOffsets()[count]) { + if (variableRange[j].start > i) { + variableRange[j].start = i; + } + if (variableRange[j].end < i) { + variableRange[j].end = i; + } + variableRange[j].gets.push_back(i); + } + } + } + } + + if (jumpOffset != SIZE_MAX) { + blocks.push_back({ i, jumpOffset }); + } + + i += byteCode->getSize(); + } + // End of information gathering and naive range finding. Beginning of actual analysis. + + for (auto &variable : variableRange) { + for (auto &element : blocks) { + if (element.start <= variable.start && element.end >= variable.end) { + variable.blocksWithRelation.push_back(std::make_pair(variableRangeInfo::Full, element)); + } else if ((element.start > variable.start && element.end >= variable.end) + || (element.start < variable.start && element.end <= variable.end)) { + variable.blocksWithRelation.push_back(std::make_pair(variableRangeInfo::Partial, element)); + } + } + } + + for (auto &var : variableRange) { + std::vector setsInBlocks; + setsInBlocks.reserve(var.sets.size()); + std::fill(setsInBlocks.begin(), setsInBlocks.end(), false); + for (size_t i = 0; i < var.sets.size(); i++) { + for (auto &block : var.blocksWithRelation) { + if (var.sets[i] > block.second.start && var.sets[i] < block.second.end) { + setsInBlocks[i] = true; + break; + } + } + } + + if (std::find(setsInBlocks.begin(), setsInBlocks.end(), false) == setsInBlocks.end()) { + var.needsInit = true; + var.start = 0; + } + + if (var.sets.empty()) { + var.start = 0; + var.needsInit = true; + } + + for (auto &getPos : var.gets) { + size_t pos = getPos; + while (pos > 0 && !var.needsInit) { + size_t lastSet = SIZE_MAX; + WASMBinaryReader::block *lastBlock = nullptr; + + for (auto &setPos : var.sets) { + if (setPos < pos || lastSet == SIZE_MAX) { + lastSet = setPos; + } + } + + for (auto &block : var.blocksWithRelation) { + if (block.second.jumpType == block::forwards) { + if (lastBlock == nullptr || (block.second.end < pos && block.second.end > lastBlock->end)) { + lastBlock = &block.second; + } + } else if (block.second.jumpType == block::forwards && block.second.start > lastBlock->start) { + lastBlock = &block.second; + } + } + + if (lastSet == SIZE_MAX) { + if (lastBlock != nullptr) { + pos = lastBlock->start; + + if (var.end < lastBlock->end) { + var.end = lastBlock->end; + } + } else { + pos = 0; + var.needsInit = true; + var.start = 0; + } + continue; + } + + if (lastBlock == nullptr) { + if (lastSet != SIZE_MAX) { + pos = 0; + } + continue; + } + + if (lastSet == SIZE_MAX && lastBlock == nullptr) { + pos = 0; + var.needsInit = 0; + var.start = 0; + continue; + } + + if (lastSet <= lastBlock->start) { + pos = lastBlock->start; + if (var.end < lastBlock->end) { + var.end = lastBlock->end; + } + } else { + pos = 0; + } + } + } + + std::vector *> seenBlocks; + bool loop = true; + while (loop) { + size_t oldEnd = var.end; + for (auto &block : var.blocksWithRelation) { + if (std::find(seenBlocks.begin(), seenBlocks.end(), &block) == seenBlocks.end()) { + seenBlocks.push_back(&block); + } + if (block.second.jumpType == block::backwards) { + if (var.start > block.second.start) { + var.start = block.second.start; + } + if (var.end < block.second.end) { + var.end = block.second.end; + } + } + } + + bool foundNewBlocks = false; + for (auto &block : blocks) { + if (oldEnd < block.start && block.start <= var.end) { + var.blocksWithRelation.push_back({ variableRangeInfo::Partial, block }); + foundNewBlocks = true; + } + } + + if (oldEnd == var.end && !foundNewBlocks) { + loop = false; + } + } + } + + // Start of variable reassignment. + Walrus::Value::Type valueTypes[] = { + Walrus::Value::Type::I32, Walrus::Value::Type::I64, + Walrus::Value::Type::F32, Walrus::Value::Type::F64, + Walrus::Value::Type::V128, Walrus::Value::Type::FuncRef + }; + size_t maxLives[] = { 0, 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(); + } + + size_t offset = 0; + 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.originalPositions = {}; + var.firstPos = UINT16_MAX; + var.assignedRanges = {}; + infos.push_back(var); + if (type == Walrus::Value::Type::I32 || type == Walrus::Value::Type::F32) { + offset += 4; + } else { + offset += Walrus::valueStackAllocatedSize(type); + } + } + } + + std::vector> constantData = {}; + for (auto &data : m_preprocessData.m_constantData) { + constantData.push_back({ data.first.type(), offset }); + + if (data.first.type() == Walrus::Value::Type::I32 || data.first.type() == Walrus::Value::Type::F32) { + offset += 4; + } else { + offset += Walrus::valueStackAllocatedSize(data.first.type()); + } + } + + std::vector offsets; + for (size_t i = 0; i < m_currentFunction->currentByteCodeSize();) { + Walrus::ByteCode *byteCode = reinterpret_cast( + const_cast(m_currentFunction->byteCode() + i)); + + for (auto &info : infos) { + if (info.end < i && !info.free) { + info.free = true; + info.end = 0; + } + } + + offsets.clear(); + 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.push_back(binOp->dstOffset()); + offsets.push_back(binOp->srcOffset()[0]); + offsets.push_back(binOp->srcOffset()[1]); + offsets.push_back(SIZE_MAX); + 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.push_back(unOp->dstOffset()); + offsets.push_back(unOp->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::I64ReinterpretF64Opcode: + case Walrus::ByteCode::F32ReinterpretI32Opcode: + case Walrus::ByteCode::F64ReinterpretI64Opcode: + case Walrus::ByteCode::I32ReinterpretF32Opcode: + case Walrus::ByteCode::MoveI32Opcode: + case Walrus::ByteCode::MoveF32Opcode: + case Walrus::ByteCode::MoveI64Opcode: + case Walrus::ByteCode::MoveF64Opcode: + case Walrus::ByteCode::MoveV128Opcode: { + Walrus::Move *move = reinterpret_cast(byteCode); + offsets.push_back(move->dstOffset()); + offsets.push_back(move->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::MemorySizeOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::MemoryInitOpcode: { + Walrus::MemoryInit *memInit = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(memInit->srcOffsets()[0]); + offsets.push_back(memInit->srcOffsets()[1]); + offsets.push_back(memInit->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::MemoryCopyOpcode: { + Walrus::MemoryCopy *memCopy = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(memCopy->srcOffsets()[0]); + offsets.push_back(memCopy->srcOffsets()[1]); + offsets.push_back(memCopy->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::MemoryFillOpcode: { + Walrus::MemoryFill *memFill = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(memFill->srcOffsets()[0]); + offsets.push_back(memFill->srcOffsets()[1]); + offsets.push_back(memFill->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::MemoryGrowOpcode: { + Walrus::MemoryGrow *memGrow = reinterpret_cast(byteCode); + offsets.push_back(memGrow->dstOffset()); + offsets.push_back(memGrow->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::GlobalGet32Opcode: + case Walrus::ByteCode::GlobalGet64Opcode: + case Walrus::ByteCode::GlobalGet128Opcode: { + Walrus::GlobalGet32 *get = reinterpret_cast(byteCode); + offsets.push_back(get->dstOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::GlobalSet32Opcode: + case Walrus::ByteCode::GlobalSet64Opcode: + case Walrus::ByteCode::GlobalSet128Opcode: { + Walrus::GlobalSet32 *globalSet = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(globalSet->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::V128Load32ZeroOpcode: + case Walrus::ByteCode::V128Load64ZeroOpcode: +#define GENERATE_MEMORY_LOAD_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_LOAD_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_EXTEND_OP(GENERATE_MEMORY_LOAD_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_LOAD_SPLAT_OP(GENERATE_MEMORY_LOAD_CODE_CASE) +#undef GENERATE_MEMORY_LOAD_CODE_CASE + { + Walrus::MemoryLoad *load = reinterpret_cast(byteCode); + offsets.push_back(load->dstOffset()); + offsets.push_back(load->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } +#define GENERATE_SIMD_MEMORY_LOAD_LANE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_SIMD_MEMORY_LOAD_LANE_CASE) +#undef GENERATE_SIMD_MEMORY_LOAD_LANE_CASE + { + Walrus::SIMDMemoryLoad *load = reinterpret_cast(byteCode); + offsets.push_back(load->dstOffset()); + offsets.push_back(load->src0Offset()); + offsets.push_back(load->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } +#define GENERATE_SIMD_MEMORY_STORE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_SIMD_MEMORY_STORE_CASE) +#undef GENERATE_SIMD_MEMORY_STORE_CASE + { + Walrus::SIMDMemoryStore *store = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(store->src0Offset()); + offsets.push_back(store->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE + { + Walrus::SIMDReplaceLane *lane = reinterpret_cast(byteCode); + offsets.push_back(lane->dstOffset()); + offsets.push_back(lane->srcOffsets()[0]); + offsets.push_back(lane->srcOffsets()[1]); + offsets.push_back(SIZE_MAX); + break; + } +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case Walrus::ByteCode::name##Opcode: + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) +#undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE + { + Walrus::SIMDExtractLane *lane = reinterpret_cast(byteCode); + offsets.push_back(lane->dstOffset()); + offsets.push_back(lane->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + 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.push_back(SIZE_MAX); + offsets.push_back(store->src0Offset()); + offsets.push_back(store->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::Load32Opcode: + case Walrus::ByteCode::Load64Opcode: { + Walrus::Load32 *load = reinterpret_cast(byteCode); + offsets.push_back(load->dstOffset()); + offsets.push_back(load->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::Store32Opcode: + case Walrus::ByteCode::Store64Opcode: { + Walrus::Store32 *store = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(store->src0Offset()); + offsets.push_back(store->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::SelectOpcode: { + Walrus::Select *select = reinterpret_cast(byteCode); + offsets.push_back(select->dstOffset()); + offsets.push_back(select->src0Offset()); + offsets.push_back(select->src1Offset()); + offsets.push_back(select->condOffset()); + break; + } + case Walrus::ByteCode::Const32Opcode: + case Walrus::ByteCode::Const64Opcode: + case Walrus::ByteCode::Const128Opcode: { + Walrus::Const32 *constant = reinterpret_cast(byteCode); + offsets.push_back(constant->dstOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::JumpIfTrueOpcode: + case Walrus::ByteCode::JumpIfFalseOpcode: { + Walrus::JumpIfFalse *jump = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + offsets.push_back(jump->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::RefFuncOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::TableSizeOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::TableGrowOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(reinterpret_cast(byteCode)->src0Offset()); + offsets.push_back(reinterpret_cast(byteCode)->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::TableGetOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(reinterpret_cast(byteCode)->srcOffset()); + offsets.push_back(SIZE_MAX); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::TableSetOpcode: { + offsets.push_back(SIZE_MAX); + offsets.push_back(reinterpret_cast(byteCode)->src0Offset()); + offsets.push_back(reinterpret_cast(byteCode)->src1Offset()); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::TableInitOpcode: { + offsets.push_back(SIZE_MAX); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[0]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[1]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::TableCopyOpcode: { + offsets.push_back(SIZE_MAX); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[0]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[1]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::TableFillOpcode: { + offsets.push_back(SIZE_MAX); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[0]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[1]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[2]); + break; + } + case Walrus::ByteCode::I8X16ShuffleOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[0]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[1]); + offsets.push_back(SIZE_MAX); + break; + } + case Walrus::ByteCode::V128BitSelectOpcode: { + offsets.push_back(reinterpret_cast(byteCode)->dstOffset()); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[0]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[1]); + offsets.push_back(reinterpret_cast(byteCode)->srcOffsets()[2]); + break; + } + // variable size instructions + case Walrus::ByteCode::EndOpcode: { + Walrus::End *end = reinterpret_cast(byteCode); + + offsets.push_back(SIZE_MAX); + for (size_t j = 0; j < end->offsetsSize(); j++) { + offsets.push_back(end->resultOffsets()[j]); + } + + break; + } + case Walrus::ByteCode::CallOpcode: { + Walrus::Call *call = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + + for (size_t j = 0; j < call->parameterOffsetsSize() + call->resultOffsetsSize(); j++) { + offsets.push_back(call->stackOffsets()[j]); + } + + break; + } + case Walrus::ByteCode::CallIndirectOpcode: { + Walrus::CallIndirect *call = reinterpret_cast(byteCode); + offsets.push_back(SIZE_MAX); + + for (size_t j = 0; j < call->parameterOffsetsSize() + call->resultOffsetsSize(); j++) { + offsets.push_back(call->stackOffsets()[j]); + } + break; + } + default: { + i += byteCode->getSize(); + continue; + } + } + + std::map offsetTypes; + + for (size_t j = 0; j < m_preprocessData.m_constantData.size(); j++) { + if (offsets[0] == m_preprocessData.m_constantData[j].second) { + setByteCodeDestination(byteCode, constantData[j].second); + offsets[0] = SIZE_MAX; + } + if (offsets[1] == m_preprocessData.m_constantData[j].second) { + setByteCodeSrc0(byteCode, constantData[j].second); + offsets[1] = SIZE_MAX; + } + if (offsets[2] == m_preprocessData.m_constantData[j].second) { + setByteCodeSrc1(byteCode, constantData[j].second); + offsets[2] = SIZE_MAX; + } + if (offsets[3] == m_preprocessData.m_constantData[j].second) { + setByteCodeExtra(byteCode, constantData[j].second); + offsets[3] = SIZE_MAX; + } + } + + for (auto &offset : offsets) { + bool local = false; + for (size_t j = m_currentFunctionType->param().size(); j < m_localInfo.size(); j++) { + if (offset == m_localInfo[j].m_position) { + local = true; + offsetTypes[m_localInfo[j].m_position] = m_localInfo[j].m_valueType; + } + } + + if (!local) { + offset = SIZE_MAX; + } + } + offsetTypes[SIZE_MAX] = Walrus::Value::Void; + + bool noLocals = true; + for (auto &offset : offsets) { + if (offset != SIZE_MAX) { + noLocals = false; + } + } + + if (noLocals) { + i += byteCode->getSize(); + continue; + } + 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 (std::find(info.assignedRanges.begin(), info.assignedRanges.end(), &range) != info.assignedRanges.end()) { + skip = true; + break; + } + } + + if (skip) { + continue; + } + + for (auto &offset : offsets) { + if (offset == SIZE_MAX) { + continue; + } + + bool alreadyAssigned = false; + for (auto &info : infos) { + if (std::find(info.originalPositions.begin(), info.originalPositions.end(), offset) != info.originalPositions.end()) { + alreadyAssigned = true; + } + } + + if (alreadyAssigned) { + continue; + } + + for (auto &info : infos) { + if (info.firstPos != UINT16_MAX && range.needsInit) { + continue; + } + + if (info.free && info.type == range.type && offsetTypes[offset] == info.type) { + info.free = false; + info.originalPositions.push_back(offset); + info.start = range.start; + info.end = range.end; + + if (info.firstPos == UINT16_MAX) { + info.firstPos = offset; + } + + info.assignedRanges.push_back(&range); + break; + } + } + } + } + offsetTypes.clear(); + + for (size_t j = 0; j < infos.size(); j++) { + if (std::find(infos[j].originalPositions.begin(), infos[j].originalPositions.end(), offsets[0]) != infos[j].originalPositions.end()) { + setByteCodeDestination(byteCode, infos[j].pos); + } + + if (std::find(infos[j].originalPositions.begin(), infos[j].originalPositions.end(), offsets[1]) != infos[j].originalPositions.end()) { + setByteCodeSrc0(byteCode, infos[j].pos); + } + + if (std::find(infos[j].originalPositions.begin(), infos[j].originalPositions.end(), offsets[2]) != infos[j].originalPositions.end()) { + setByteCodeSrc1(byteCode, infos[j].pos); + } + + if (std::find(infos[j].originalPositions.begin(), infos[j].originalPositions.end(), offsets[3]) != infos[j].originalPositions.end()) { + setByteCodeExtra(byteCode, infos[j].pos); + } + } + + i += byteCode->getSize(); + } + + for (auto &end : ends) { + for (size_t i = 0; i < end->offsetsSize(); i++) { + for (size_t j = 0; j < m_preprocessData.m_constantData.size(); j++) { + if (m_preprocessData.m_constantData[j].second == end->resultOffsets()[i]) { + end->resultOffsets()[i] = constantData[j].second; + } + } + + for (auto &info : infos) { + if (std::find(info.originalPositions.begin(), info.originalPositions.end(), end->resultOffsets()[i]) != info.originalPositions.end()) { + end->resultOffsets()[i] = info.pos; + +#if defined(WALRUS_32) + switch (infos[i].type) { + case Walrus::Value::Type::I64: + case Walrus::Value::Type::F64: { + i++; + end->resultOffsets()[i] = info.pos + 4; + break; + } + case Walrus::Value::Type::V128: { + for (unsigned idx = 1; idx < 4; idx++) { + i++; + end->resultOffsets()[i] = info.pos + (idx * 4); + } + break; + } + default: { + break; + } + } +#else + if (info.type == Walrus::Value::Type::V128) { + i++; + end->resultOffsets()[i] = info.pos + 8; + } +#endif + break; + } + } + } + } + + + for (auto &code : calls) { + Walrus::ByteCodeStackOffset *stackOffsets = nullptr; + size_t size = 0; + switch (code->opcode()) { + case Walrus::ByteCode::CallOpcode: { + Walrus::Call *call = reinterpret_cast(code); + stackOffsets = call->stackOffsets(); + size = call->parameterOffsetsSize() + call->resultOffsetsSize(); + + break; + } + case Walrus::ByteCode::CallIndirectOpcode: { + Walrus::CallIndirect *call = reinterpret_cast(code); + stackOffsets = call->stackOffsets(); + size = call->parameterOffsetsSize() + call->resultOffsetsSize(); + break; + } + default: { + RELEASE_ASSERT_NOT_REACHED(); + break; + } + } + + for (size_t j = 0; j < size; j++) { + for (auto &info : infos) { + if (std::find(info.originalPositions.begin(), info.originalPositions.end(), stackOffsets[j]) != info.originalPositions.end()) { + stackOffsets[j] = info.pos; + +#if defined(WALRUS_32) + switch (info.type) { + case Walrus::Value::Type::I64: + case Walrus::Value::Type::F64: { + j++; + stackOffsets[j] = info.pos + 4; + break; + } + case Walrus::Value::Type::V128: { + for (unsigned idx = 1; idx < 4; idx++) { + j++; + stackOffsets[j] = info.pos + (idx * 4); + } + break; + } + default: { + break; + } + } +#else + if (info.type == Walrus::Value::Type::V128) { + j++; + stackOffsets[j] = info.pos + 8; + } +#endif + break; + } + } + + + for (size_t k = 0; k < m_preprocessData.m_constantData.size(); k++) { + if (m_preprocessData.m_constantData[k].second == stackOffsets[j]) { + stackOffsets[j] = constantData[k].second; + } + } + } + } + + + for (auto &info : infos) { + for (auto &brTable : brTables) { + if (std::find(info.originalPositions.begin(), info.originalPositions.end(), brTable->condOffset()) != info.originalPositions.end()) { + brTable->setCondOffset(info.pos); + break; + } + } + } + + + for (size_t i = 0; i < infos.size(); i++) { + if (!infos[i].originalPositions.empty()) { + m_localInfo[i] = { infos[i].type, infos[i].pos }; + m_currentFunction->m_local[i] = infos[i].type; + } + } + + size_t constSize = 0; + for (auto &info : infos) { + for (auto &range : info.assignedRanges) { + if (range->needsInit) { + switch (info.type) { +#if defined(WALRUS_32) + case Walrus::Value::FuncRef: +#endif + case Walrus::Value::I32: { + case Walrus::Value::F32: + Walrus::Const32 const32 = Walrus::Const32(info.pos, 0); + char *first = (char *)&const32; + + for (size_t i = 0; i < sizeof(Walrus::Const32); i++) { + m_currentFunction->m_byteCode.insert(i, *first); + first++; + } + + constSize += sizeof(Walrus::Const32); + break; + } +#if defined(WALRUS_64) + case Walrus::Value::FuncRef: +#endif + case Walrus::Value::I64: + case Walrus::Value::F64: { + Walrus::Const64 const64 = Walrus::Const64(info.pos, 0); + char *first = (char *)&const64; + + for (size_t i = 0; i < sizeof(Walrus::Const64); i++) { + m_currentFunction->m_byteCode.insert(i, *first); + first++; + } + + constSize += sizeof(Walrus::Const64); + break; + } + case Walrus::Value::V128: { + uint8_t empty[16] = { + 0 + }; + + Walrus::Const128 const128 = Walrus::Const128(info.pos, empty); + char *first = (char *)&const128; + + for (size_t i = 0; i < sizeof(Walrus::Const128); i++) { + m_currentFunction->m_byteCode.insert(i, *first); + first++; + } + + constSize += sizeof(Walrus::Const128); + break; + } + default: { + RELEASE_ASSERT_NOT_REACHED(); + break; + } + } + } + } + } + + for (auto &info : infos) { + for (auto &range : info.assignedRanges) { + if (range->start != 0) { + range->start += constSize; + } + range->end += constSize; + } + } + +#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->start); + debugInfo.ends.push_back(range->end); + } + + 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, {}, {} }); + } + + for (size_t i = 0; i < constantData.size(); i++) { + m_currentFunction->m_constantDebugData[i].second = constantData[i].second; + } +#endif + + // variable life analysis end + } }; } // namespace wabt @@ -2750,7 +4665,7 @@ void WASMParsingResult::clear() } } -std::pair, std::string> WASMParser::parseBinary(Store* store, const std::string& filename, const uint8_t* data, size_t len, const uint32_t JITFlags) +std::pair, std::string> WASMParser::parseBinary(Store *store, const std::string &filename, const uint8_t *data, size_t len, const uint32_t JITFlags) { wabt::WASMBinaryReader delegate; @@ -2759,7 +4674,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 (JITFlags & JITFlagValue::useJIT) { module->jitCompile(nullptr, 0, JITFlags); } diff --git a/src/runtime/Module.cpp b/src/runtime/Module.cpp index 3d6c98c61..83019a775 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -442,8 +442,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 || m_localDebugData[i].starts.empty()) { + printf("\n(local %zu, optimized out)", 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); @@ -452,6 +462,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 c3aff6160..e5ea277f7 100644 --- a/src/runtime/Module.h +++ b/src/runtime/Module.h @@ -182,6 +182,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(); @@ -251,7 +259,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/initialization.wast b/test/basic/initialization.wast new file mode 100644 index 000000000..ca12d8260 --- /dev/null +++ b/test/basic/initialization.wast @@ -0,0 +1,117 @@ +(module + +(func (export "f1") (result i32) + (local i32) + + i32.const 0 + (if + (then + i32.const 1 + local.set 0 + ) + ) + + local.get 0 + +) + +(func (export "f2") (result i32) + (local i32) + + (loop $loop + + i32.const 1 + local.set 0 + + i32.const 0 + br_if $loop + ) + + local.get 0 +) + +(func (export "f3") (result i32) + (local i32) + + local.get 0 +) + +(func (export "f4") (result i32) + (local i32) + + local.get 0 + i32.const 1 + i32.add + local.tee 0 +) + + +(func (export "f5") (result i32) + (local i32 i32 i32) + (block $while + (loop $loop + i32.const 1 + br_if $while + + i32.const 1 + local.set 0 + + br $loop + ) + ) + + i32.const 1 + local.set 2 + (block $while + (loop $loop + local.get 2 + br_if $while + + local.get 0 + local.set 1 + + i32.const 1 + local.get 2 + i32.sub + local.set 2 + + br $loop + ) + ) + + local.get 1 +) + +(func (export "f6") (param i32 ) (result i32) + (local i32) + + (block $end + (block + (block + local.get 0 + (br_table 0 1 2) + ) + + i32.const 1 + local.tee 1 + + return + ) + i32.const 2 + local.set 1 + ) + + local.get 1 +) + +) + +(assert_return (invoke "f1") (i32.const 0)) +(assert_return (invoke "f2") (i32.const 1)) +(assert_return (invoke "f3") (i32.const 0)) +(assert_return (invoke "f4") (i32.const 1)) +(assert_return (invoke "f5") (i32.const 0)) +(assert_return (invoke "f6" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "f6" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "f6" (i32.const 2)) (i32.const 0)) + 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..19d2746a9 --- /dev/null +++ b/test/basic/local_sets.wast @@ -0,0 +1,109 @@ +(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))