diff --git a/asd.wast b/asd.wast new file mode 100644 index 000000000..518344bd2 --- /dev/null +++ b/asd.wast @@ -0,0 +1,175 @@ +(module + (type (;0;) (func)) + (type (;1;) (func (param i32 i32 i32))) + (import "spectest" "print_i32" (func $print_i32 (param i32))) + + (global $max i32 (i32.const 3)) + + (func $qs (type 1) (param i32 i32 i32) + (local i32 i32 i32 i32 i32 i32 i32 i32) + local.get 1 + local.get 2 + i32.lt_s + if ;; label = @1 + local.get 0 + local.get 2 + i32.const 2 + i32.shl + i32.add + local.set 7 + loop ;; label = @2 + i32.const 0 + local.set 3 + local.get 2 + local.get 1 + i32.sub + local.tee 8 + i32.const 0 + i32.gt_s + if ;; label = @3 + local.get 7 + i32.load + local.set 6 + i32.const 0 + local.set 4 + loop ;; label = @4 + block ;; label = @5 + local.get 6 + local.get 0 + local.get 1 + local.get 3 + i32.add + i32.const 2 + i32.shl + i32.add + local.tee 5 + i32.load + local.tee 9 + i32.gt_s + if ;; label = @6 + local.get 3 + i32.const 1 + i32.add + local.set 3 + br 1 (;@5;) + end + local.get 5 + local.get 0 + local.get 2 + local.get 4 + i32.sub + i32.const 2 + i32.shl + i32.add + local.tee 5 + i32.const 4 + i32.sub + local.tee 10 + i32.load + i32.store + local.get 5 + local.get 9 + i32.store + local.get 10 + local.get 6 + i32.store + local.get 4 + i32.const 1 + i32.add + local.set 4 + end + local.get 3 + local.get 4 + i32.add + local.get 8 + i32.lt_s + br_if 0 (;@4;) + end + end + local.get 0 + local.get 1 + local.get 1 + local.get 3 + i32.add + local.tee 1 + i32.const 1 + i32.sub + call $qs + local.get 1 + i32.const 1 + i32.add + local.tee 1 + local.get 2 + i32.lt_s + br_if 0 (;@2;) + end + end) + + + + (func $print (type 0) + (local i32 i32) + global.get $max + local.set 1 + (loop + local.get 0 + i32.const 4 + i32.mul + i32.load + call $print_i32 + + local.get 0 + i32.const 1 + i32.add + local.tee 0 + local.get 1 + i32.ne + br_if 0 + ) + + ) + + (func $start (type 0) + (local i32 i32) + global.get $max + local.set 1 + + (loop + local.get 0 + i32.const 4 + i32.mul + local.get 1 + local.get 0 + i32.sub + i32.store + + local.get 0 + i32.const 1 + i32.add + local.tee 0 + local.get 1 + i32.ne + br_if 0 + ) +;; call $print + i32.const 0 + i32.const 0 + global.get $max + call $qs +;; call $print + ) + + + (memory (;0;) 256 256) + + (start $start) + + (func (export "read") (param i32) (result i32) + (i32.load (local.get 0)) + ) + +) + +(assert_return (invoke "read" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "read" (i32.const 4)) (i32.const 1)) +(assert_return (invoke "read" (i32.const 8)) (i32.const 2)) diff --git a/notes.txt b/notes.txt new file mode 100644 index 000000000..733ef0e93 --- /dev/null +++ b/notes.txt @@ -0,0 +1,4 @@ +normal fails: +huffman (out of bounds memory) +simd stuff +sometimes stuff with jit, due to reg alloc 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..fa4637e7a 100644 --- a/src/parser/WASMParser.cpp +++ b/src/parser/WASMParser.cpp @@ -15,12 +15,17 @@ */ #include "Walrus.h" -#include "parser/WASMParser.h" #include "interpreter/ByteCode.h" -#include "runtime/Store.h" +#include "parser/WASMParser.h" +#include "runtime/Function.h" #include "runtime/Module.h" +#include "runtime/ObjectType.h" +#include "runtime/Store.h" +#include "runtime/Value.h" #include "wabt/walrus/binary-reader-walrus.h" +#include +#include namespace wabt { @@ -43,7 +48,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 +156,65 @@ 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 +223,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - VMStackInfo(const VMStackInfo& src) + VMStackInfo(const VMStackInfo &src) : m_reader(src.m_reader) , m_valueType(src.m_valueType) , m_position(src.m_position) @@ -171,11 +232,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { } - ~VMStackInfo() - { - } + ~VMStackInfo() {} - const VMStackInfo& operator=(const VMStackInfo& src) + const VMStackInfo &operator=(const VMStackInfo &src) { m_valueType = src.m_valueType; m_position = src.m_position; @@ -225,7 +284,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,24 +321,27 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { std::vector m_jumpToEndBrInfo; - BlockInfo(BlockType type, Type returnValueType, WASMBinaryReader& binaryReader) + BlockInfo(BlockType type, Type returnValueType, + WASMBinaryReader &binaryReader) : m_blockType(type) , m_returnValueType(returnValueType) , m_position(0) , m_functionStackSizeSoFar(binaryReader.m_functionStackSizeSoFar) - , m_shouldRestoreVMStackAtEnd((m_returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[m_returnValueType]->result().size()) - || m_returnValueType != Type::Void) + , m_shouldRestoreVMStackAtEnd( + (m_returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[m_returnValueType]->result().size()) || m_returnValueType != Type::Void) , m_byteCodeGenerationStopped(false) , m_seenBranch(false) { if (returnValueType.IsIndex() && binaryReader.m_result.m_functionTypes[returnValueType]->param().size()) { // record parameter positions - auto& param = binaryReader.m_result.m_functionTypes[returnValueType]->param(); + auto ¶m = binaryReader.m_result.m_functionTypes[returnValueType]->param(); auto endIter = binaryReader.m_vmStack.rbegin() + param.size(); auto iter = binaryReader.m_vmStack.rbegin(); while (iter != endIter) { if (iter->position() != iter->nonOptimizedPosition()) { - binaryReader.generateMoveCodeIfNeeds(iter->position(), iter->nonOptimizedPosition(), iter->valueType()); + binaryReader.generateMoveCodeIfNeeds(iter->position(), + iter->nonOptimizedPosition(), + iter->valueType()); iter->setPosition(iter->nonOptimizedPosition()); if (binaryReader.m_preprocessData.m_inPreprocess && iter->hasValidLocalIndex()) { size_t pos = *binaryReader.m_readerOffsetPointer; @@ -306,8 +368,9 @@ 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 +400,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { std::vector m_usageInfo; }; - PreprocessData(WASMBinaryReader& reader) + PreprocessData(WASMBinaryReader &reader) : m_inPreprocess(false) , m_reader(reader) { @@ -356,7 +419,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,16 +430,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_inPreprocess) { size_t pushCount = 0; size_t pos = *m_reader.m_readerOffsetPointer; - for (const auto& stack : m_reader.m_vmStack) { + for (const auto &stack : m_reader.m_vmStack) { if (stack.localIndex() == localIndex) { pushCount++; } } - m_localVariableInfo[localIndex].m_usageInfo.push_back(LocalVariableInfo::UsageInfo(pos, pushCount)); + m_localVariableInfo[localIndex].m_usageInfo.push_back( + LocalVariableInfo::UsageInfo(pos, pushCount)); if (!m_localVariableInfo[localIndex].m_needsExplicitInitOnStartup) { if (!m_localVariableInfo[localIndex].m_writePlacesBetweenBranches.size()) { 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 +485,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,26 +514,24 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { void organizeConstantData() { std::sort(m_constantData.begin(), m_constantData.end(), - [](const std::pair& a, const std::pair& b) -> bool { + [](const std::pair &a, + const std::pair &b) -> bool { return a.second > b.second; }); } - void organizeData() - { - organizeConstantData(); - } + void organizeData() { organizeConstantData(); } bool m_inPreprocess; - WASMBinaryReader& m_reader; + WASMBinaryReader &m_reader; std::vector m_localVariableInfo; // std::vector> m_constantData; }; bool m_inInitExpr; - Walrus::ModuleFunction* m_currentFunction; - Walrus::FunctionType* m_currentFunctionType; + Walrus::ModuleFunction *m_currentFunction; + Walrus::FunctionType *m_currentFunctionType; uint16_t m_initialFunctionStackSize; uint16_t m_functionStackSizeSoFar; @@ -496,25 +558,28 @@ 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; } @@ -526,17 +591,23 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return pos; } - void pushVMStack(Walrus::Value::Type type, size_t pos, size_t localIndex = std::numeric_limits::max()) + void pushVMStack(Walrus::Value::Type type, size_t pos, + size_t localIndex = std::numeric_limits::max()) { if (localIndex != std::numeric_limits::max()) { m_preprocessData.addLocalVariableUsage(localIndex); } - m_vmStack.push_back(VMStackInfo(*this, type, pos, m_functionStackSizeSoFar, localIndex)); + m_vmStack.push_back( + VMStackInfo(*this, type, pos, m_functionStackSizeSoFar, localIndex)); size_t allocSize = Walrus::valueStackAllocatedSize(type); // FIXME too many stack usage. we could not support this(yet) ASSERT(m_functionStackSizeSoFar + allocSize <= std::numeric_limits::max()); + 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); @@ -555,7 +626,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { if (m_preprocessData.m_inPreprocess) { if (info.hasValidLocalIndex()) { size_t pos = *m_readerOffsetPointer; - auto iter = m_preprocessData.m_localVariableInfo[info.localIndex()].m_usageInfo.rbegin(); + auto iter = m_preprocessData.m_localVariableInfo[info.localIndex()] + .m_usageInfo.rbegin(); while (true) { ASSERT(iter != m_preprocessData.m_localVariableInfo[info.localIndex()].m_usageInfo.rend()); if (iter->m_endPosition == std::numeric_limits::max()) { @@ -570,7 +642,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 +665,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; @@ -619,12 +691,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); @@ -633,14 +705,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { inline bool canBeInverted(size_t stackPos) { /** - * m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize() - * checks if last byteCode is I32Eqz + * m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == + * m_currentFunction->currentByteCodeSize() checks if last byteCode is + * I32Eqz * - * m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos - * checks if the output of I32Eqz is the input of JumpIfTrue/JumpIfFalse - */ - return (m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize()) - && (m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos); + * m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() + * == stackPos checks if the output of I32Eqz is the input of + * JumpIfTrue/JumpIfFalse + */ + return (m_lastI32EqzPos + sizeof(Walrus::I32Eqz) == m_currentFunction->currentByteCodeSize()) && (m_currentFunction->peekByteCode(m_lastI32EqzPos)->dstOffset() == stackPos); } Walrus::Optional lookaheadUnsigned8(size_t offset = 0) @@ -702,8 +775,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 +792,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,34 +822,41 @@ 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]; - m_result.m_functions.push_back( - new Walrus::ModuleFunction(ft)); + Walrus::FunctionType *ft = m_result.m_functionTypes[sigIndex]; + m_result.m_functions.push_back(new Walrus::ModuleFunction(ft)); m_result.m_imports.push_back(new Walrus::ImportType( Walrus::ImportType::Function, moduleName, fieldName, ft)); } - virtual void OnImportGlobal(Index importIndex, std::string moduleName, std::string fieldName, Index globalIndex, Type type, bool mutable_) override + virtual void OnImportGlobal(Index importIndex, std::string moduleName, + std::string fieldName, Index globalIndex, + Type type, bool mutable_) override { ASSERT(globalIndex == m_result.m_globalTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); - m_result.m_globalTypes.push_back(new Walrus::GlobalType(toValueKind(type), mutable_)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Global, - moduleName, fieldName, m_result.m_globalTypes[globalIndex])); + m_result.m_globalTypes.push_back( + new Walrus::GlobalType(toValueKind(type), mutable_)); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Global, moduleName, + fieldName, m_result.m_globalTypes[globalIndex])); } - virtual void OnImportTable(Index importIndex, std::string moduleName, std::string fieldName, Index tableIndex, Type type, size_t initialSize, size_t maximumSize) override + virtual void OnImportTable(Index importIndex, std::string moduleName, + std::string fieldName, Index tableIndex, Type type, + size_t initialSize, size_t maximumSize) override { ASSERT(tableIndex == m_result.m_tableTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); ASSERT(type == Type::FuncRef || type == Type::ExternRef); - m_result.m_tableTypes.push_back(new Walrus::TableType(type == Type::FuncRef ? Walrus::Value::Type::FuncRef : Walrus::Value::Type::ExternRef, initialSize, maximumSize)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Table, - moduleName, fieldName, m_result.m_tableTypes[tableIndex])); + m_result.m_tableTypes.push_back(new Walrus::TableType( + type == Type::FuncRef ? Walrus::Value::Type::FuncRef + : Walrus::Value::Type::ExternRef, + initialSize, maximumSize)); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Table, moduleName, fieldName, + m_result.m_tableTypes[tableIndex])); } virtual void OnImportMemory(Index importIndex, std::string moduleName, std::string fieldName, Index memoryIndex, size_t initialSize, size_t maximumSize, bool isShared) override @@ -789,14 +869,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { moduleName, fieldName, m_result.m_memoryTypes[memoryIndex])); } - virtual void OnImportTag(Index importIndex, std::string moduleName, std::string fieldName, Index tagIndex, Index sigIndex) override + virtual void OnImportTag(Index importIndex, std::string moduleName, + std::string fieldName, Index tagIndex, + Index sigIndex) override { ASSERT(tagIndex == m_result.m_tagTypes.size()); ASSERT(m_result.m_imports.size() == importIndex); m_result.m_tagTypes.push_back(new Walrus::TagType(sigIndex)); - m_result.m_imports.push_back(new Walrus::ImportType( - Walrus::ImportType::Tag, - moduleName, fieldName, m_result.m_tagTypes[tagIndex])); + m_result.m_imports.push_back( + new Walrus::ImportType(Walrus::ImportType::Tag, moduleName, fieldName, + m_result.m_tagTypes[tagIndex])); } virtual void OnExportCount(Index count) override @@ -804,10 +886,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_exports.reserve(count); } - virtual void OnExport(int kind, Index exportIndex, std::string name, Index itemIndex) override + virtual void OnExport(int kind, Index exportIndex, std::string name, + Index itemIndex) override { ASSERT(m_result.m_exports.size() == exportIndex); - m_result.m_exports.push_back(new Walrus::ExportType(static_cast(kind), name, itemIndex)); + m_result.m_exports.push_back(new Walrus::ExportType( + static_cast(kind), name, itemIndex)); } /* Table section */ @@ -816,11 +900,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_tableTypes.reserve(count); } - virtual void OnTable(Index index, Type type, size_t initialSize, size_t maximumSize) override + virtual void OnTable(Index index, Type type, size_t initialSize, + size_t maximumSize) override { ASSERT(index == m_result.m_tableTypes.size()); ASSERT(type == Type::FuncRef || type == Type::ExternRef); - m_result.m_tableTypes.push_back(new Walrus::TableType(type == Type::FuncRef ? Walrus::Value::Type::FuncRef : Walrus::Value::Type::ExternRef, initialSize, maximumSize)); + m_result.m_tableTypes.push_back(new Walrus::TableType( + type == Type::FuncRef ? Walrus::Value::Type::FuncRef + : Walrus::Value::Type::ExternRef, + initialSize, maximumSize)); } virtual void OnElemSegmentCount(Index count) override @@ -828,7 +916,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_elements.reserve(count); } - virtual void BeginElemSegment(Index index, Index tableIndex, uint8_t flags) override + virtual void BeginElemSegment(Index index, Index tableIndex, + uint8_t flags) override { m_elementTableIndex = tableIndex; m_elementOffsetFunction = nullptr; @@ -837,7 +926,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void BeginElemSegmentInitExpr(Index index) override { - beginFunction(new Walrus::ModuleFunction(Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), true); + beginFunction( + new Walrus::ModuleFunction( + Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), + true); } virtual void EndElemSegmentInitExpr(Index index) override @@ -846,9 +938,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { endFunction(); } - virtual void OnElemSegmentElemType(Index index, Type elemType) override - { - } + virtual void OnElemSegmentElemType(Index index, Type elemType) override {} virtual void OnElemSegmentElemExprCount(Index index, Index count) override { @@ -897,21 +987,22 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_result.m_datas.reserve(count); } - virtual void BeginDataSegment(Index index, Index memoryIndex, uint8_t flags) override + virtual void BeginDataSegment(Index index, Index memoryIndex, + uint8_t flags) override { ASSERT(index == m_result.m_datas.size()); - beginFunction(new Walrus::ModuleFunction(Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), true); + beginFunction( + new Walrus::ModuleFunction( + Walrus::Store::getDefaultFunctionType(Walrus::Value::I32)), + true); } - virtual void BeginDataSegmentInitExpr(Index index) override - { - } + virtual void BeginDataSegmentInitExpr(Index index) override {} - virtual void EndDataSegmentInitExpr(Index index) override - { - } + virtual void EndDataSegmentInitExpr(Index index) override {} - virtual void OnDataSegmentData(Index index, const void* data, Address size) override + virtual void OnDataSegmentData(Index index, const void *data, + Address size) override { m_memoryInitData.resizeWithUninitializedValues(size); memcpy(m_memoryInitData.data(), data, size); @@ -920,7 +1011,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void EndDataSegment(Index index) override { ASSERT(index == m_result.m_datas.size()); - m_result.m_datas.push_back(new Walrus::Data(m_currentFunction, std::move(m_memoryInitData))); + m_result.m_datas.push_back( + new Walrus::Data(m_currentFunction, std::move(m_memoryInitData))); endFunction(); } @@ -935,7 +1027,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(m_currentFunction == nullptr); ASSERT(m_currentFunctionType == nullptr); ASSERT(m_result.m_functions.size() == index); - m_result.m_functions.push_back(new Walrus::ModuleFunction(m_result.m_functionTypes[sigIndex])); + m_result.m_functions.push_back( + new Walrus::ModuleFunction(m_result.m_functionTypes[sigIndex])); } virtual void OnGlobalCount(Index count) override @@ -946,29 +1039,24 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void BeginGlobal(Index index, Type type, bool mutable_) override { ASSERT(m_result.m_globalTypes.size() == index); - m_result.m_globalTypes.push_back(new Walrus::GlobalType(toValueKind(type), mutable_)); + m_result.m_globalTypes.push_back( + new Walrus::GlobalType(toValueKind(type), mutable_)); } virtual void BeginGlobalInitExpr(Index index) override { - auto ft = Walrus::Store::getDefaultFunctionType(m_result.m_globalTypes[index]->type()); - Walrus::ModuleFunction* mf = new Walrus::ModuleFunction(ft); + auto ft = Walrus::Store::getDefaultFunctionType( + m_result.m_globalTypes[index]->type()); + Walrus::ModuleFunction *mf = new Walrus::ModuleFunction(ft); m_result.m_globalTypes[index]->setFunction(mf); beginFunction(mf, true); } - virtual void EndGlobalInitExpr(Index index) override - { - endFunction(); - } + virtual void EndGlobalInitExpr(Index index) override { endFunction(); } - virtual void EndGlobal(Index index) override - { - } + virtual void EndGlobal(Index index) override {} - virtual void EndGlobalSection() override - { - } + virtual void EndGlobalSection() override {} virtual void OnTagCount(Index count) override { @@ -1034,6 +1122,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_shouldContinueToGenerateByteCode = true; m_currentFunction->m_byteCode.clear(); + m_currentFunction->m_catchInfo.clear(); m_blockInfo.clear(); m_catchInfo.clear(); @@ -1056,10 +1145,11 @@ 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 - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - auto& info = m_localInfo[i]; + // 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]; if (Walrus::hasCPUWordAlignedSize(info.m_valueType) || needsCPUWordAlignedAddress(info.m_valueType)) { info.m_position = m_initialFunctionStackSize; m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(info.m_valueType); @@ -1074,8 +1164,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } // pack rest values - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - auto& info = m_localInfo[i]; + for (size_t i = m_currentFunctionType->param().size(); + i < m_localInfo.size(); i++) { + auto &info = m_localInfo[i]; if (!Walrus::hasCPUWordAlignedSize(info.m_valueType) && !needsCPUWordAlignedAddress(info.m_valueType)) { info.m_position = m_initialFunctionStackSize; m_initialFunctionStackSize += Walrus::valueSize(info.m_valueType); @@ -1099,30 +1190,36 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_currentFunction->m_requiredStackSize = m_functionStackSizeSoFar; // Explicit init local variable if needs - for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) { - if (m_preprocessData.m_localVariableInfo[i].m_needsExplicitInitOnStartup) { - 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 - } + // 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( + // Walrus::ModuleFunction::LocalDebugInfo{ + // m_localInfo[i].m_position, {}, {} }); + // #endif + //} // init constant space for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) { - const auto& constValue = m_preprocessData.m_constantData[i].first; + const auto &constValue = m_preprocessData.m_constantData[i].first; auto constType = m_preprocessData.m_constantData[i].first.type(); auto constPos = m_preprocessData.m_constantData[i].second; size_t constSize = Walrus::valueSize(constType); @@ -1130,24 +1227,27 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { uint8_t constantBuffer[16]; constValue.writeToMemory(constantBuffer); if (constSize == 4) { - pushByteCode(Walrus::Const32(constPos, *reinterpret_cast(constantBuffer)), WASMOpcode::I32ConstOpcode); + pushByteCode(Walrus::Const32(constPos, *reinterpret_cast(constantBuffer)), + WASMOpcode::I32ConstOpcode); } else if (constSize == 8) { - pushByteCode(Walrus::Const64(constPos, *reinterpret_cast(constantBuffer)), WASMOpcode::I64ConstOpcode); + pushByteCode(Walrus::Const64(constPos, *reinterpret_cast(constantBuffer)), + WASMOpcode::I64ConstOpcode); } else { ASSERT(constSize == 16); - pushByteCode(Walrus::Const128(constPos, constantBuffer), WASMOpcode::V128ConstOpcode); + pushByteCode(Walrus::Const128(constPos, constantBuffer), + WASMOpcode::V128ConstOpcode); } #if !defined(NDEBUG) - m_currentFunction->m_constantDebugData.pushBack(m_preprocessData.m_constantData[i]); + m_currentFunction->m_constantDebugData.pushBack( + m_preprocessData.m_constantData[i]); #endif } } - virtual void OnOpcode(uint32_t opcode) override - { - } + virtual void OnOpcode(uint32_t opcode) override {} - uint16_t computeFunctionParameterOrResultOffsetCount(const Walrus::ValueTypeVector& types) + uint16_t computeFunctionParameterOrResultOffsetCount( + const Walrus::ValueTypeVector &types) { uint16_t result = 0; for (auto t : types) { @@ -1157,8 +1257,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } template - void generateCallExpr(CodeType* code, uint16_t parameterCount, uint16_t resultCount, - Walrus::FunctionType* functionType) + void generateCallExpr(CodeType *code, uint16_t parameterCount, + uint16_t resultCount, + Walrus::FunctionType *functionType) { size_t offsetIndex = 0; size_t siz = functionType->param().size(); @@ -1193,10 +1294,12 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto callPos = m_currentFunction->currentByteCodeSize(); auto parameterCount = computeFunctionParameterOrResultOffsetCount(functionType->param()); auto resultCount = computeFunctionParameterOrResultOffsetCount(functionType->result()); - pushByteCode(Walrus::Call(index, parameterCount, resultCount), WASMOpcode::CallOpcode); + pushByteCode(Walrus::Call(index, parameterCount, resultCount), + WASMOpcode::CallOpcode); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); auto code = m_currentFunction->peekByteCode(callPos); generateCallExpr(code, parameterCount, resultCount, functionType); @@ -1209,23 +1312,26 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto callPos = m_currentFunction->currentByteCodeSize(); auto parameterCount = computeFunctionParameterOrResultOffsetCount(functionType->param()); auto resultCount = computeFunctionParameterOrResultOffsetCount(functionType->result()); - pushByteCode(Walrus::CallIndirect(popVMStack(), tableIndex, functionType, parameterCount, resultCount), + pushByteCode(Walrus::CallIndirect(popVMStack(), tableIndex, functionType, + parameterCount, resultCount), WASMOpcode::CallIndirectOpcode); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * (parameterCount + resultCount))); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); auto code = m_currentFunction->peekByteCode(callPos); generateCallExpr(code, parameterCount, resultCount, functionType); } - bool processConstValue(const Walrus::Value& value) + bool processConstValue(const Walrus::Value &value) { if (!m_inInitExpr) { m_preprocessData.addConstantData(value); if (!m_preprocessData.m_inPreprocess) { for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) { if (m_preprocessData.m_constantData[i].first == value) { - pushVMStack(value.type(), m_preprocessData.m_constantData[i].second); + pushVMStack(value.type(), + m_preprocessData.m_constantData[i].second); return true; } } @@ -1234,26 +1340,32 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return false; } - virtual void OnI32ConstExpr(uint32_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::I32, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::I32, reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::I32), value), WASMOpcode::I32ConstOpcode); + pushByteCode( + Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::I32), value), + WASMOpcode::I32ConstOpcode); } virtual void OnI64ConstExpr(uint64_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::I64, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::I64, + reinterpret_cast(&value)))) { return; } - pushByteCode(Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::I64), value), WASMOpcode::I64ConstOpcode); + pushByteCode( + Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::I64), + value), + WASMOpcode::I64ConstOpcode); } virtual void OnF32ConstExpr(uint32_t value) override { - if (processConstValue(Walrus::Value(Walrus::Value::Type::F32, reinterpret_cast(&value)))) { + if (processConstValue(Walrus::Value(Walrus::Value::Type::F32, + reinterpret_cast(&value)))) { return; } pushByteCode(Walrus::Const32(computeExprResultPosition(Walrus::Value::Type::F32), value), WASMOpcode::F32ConstOpcode); @@ -1261,18 +1373,25 @@ 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); + pushByteCode( + Walrus::Const64(computeExprResultPosition(Walrus::Value::Type::F64), + value), + WASMOpcode::F64ConstOpcode); } - virtual void OnV128ConstExpr(uint8_t* value) override + virtual void OnV128ConstExpr(uint8_t *value) override { if (processConstValue(Walrus::Value(Walrus::Value::Type::V128, value))) { return; } - pushByteCode(Walrus::Const128(computeExprResultPosition(Walrus::Value::Type::V128), value), WASMOpcode::V128ConstOpcode); + pushByteCode( + Walrus::Const128(computeExprResultPosition(Walrus::Value::Type::V128), + value), + WASMOpcode::V128ConstOpcode); } size_t computeExprResultPosition(Walrus::Value::Type type) @@ -1299,7 +1418,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { bool canUseDirectReference = true; size_t pos = *m_readerOffsetPointer; - for (const auto& r : m_preprocessData.m_localVariableInfo[localIndex].m_usageInfo) { + for (const auto &r : + m_preprocessData.m_localVariableInfo[localIndex].m_usageInfo) { if (r.m_startPosition <= pos && pos <= r.m_endPosition) { if (r.m_hasWriteUsage) { canUseDirectReference = false; @@ -1343,12 +1463,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto sz = Walrus::valueSize(valueType); auto stackPos = computeExprResultPosition(valueType); if (sz == 4) { - pushByteCode(Walrus::GlobalGet32(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet32(stackPos, index), + WASMOpcode::GlobalGetOpcode); } else if (sz == 8) { - pushByteCode(Walrus::GlobalGet64(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet64(stackPos, index), + WASMOpcode::GlobalGetOpcode); } else { ASSERT(sz == 16); - pushByteCode(Walrus::GlobalGet128(stackPos, index), WASMOpcode::GlobalGetOpcode); + pushByteCode(Walrus::GlobalGet128(stackPos, index), + WASMOpcode::GlobalGetOpcode); } } @@ -1360,35 +1483,42 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == valueType); auto sz = Walrus::valueSize(valueType); if (sz == 4) { - pushByteCode(Walrus::GlobalSet32(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet32(stackPos, index), + WASMOpcode::GlobalSetOpcode); } else if (sz == 8) { - pushByteCode(Walrus::GlobalSet64(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet64(stackPos, index), + WASMOpcode::GlobalSetOpcode); } else { - pushByteCode(Walrus::GlobalSet128(stackPos, index), WASMOpcode::GlobalSetOpcode); + pushByteCode(Walrus::GlobalSet128(stackPos, index), + WASMOpcode::GlobalSetOpcode); } popVMStack(); } - virtual void OnDropExpr() override - { - popVMStack(); - } + virtual void OnDropExpr() override { popVMStack(); } virtual void OnBinaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto src1 = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); generateBinaryCode(code, src0, src1, dst); } virtual void OnUnaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src = popVMStack(); auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); generateUnaryCode(code, src, dst); @@ -1397,13 +1527,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnTernaryExpr(uint32_t opcode) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[2]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[2]) + == peekVMStackValueType()); auto c = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto rhs = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto lhs = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { case WASMOpcode::V128BitSelectOpcode: pushByteCode(Walrus::V128BitSelect(lhs, rhs, c, dst), code); @@ -1421,13 +1558,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { bool isInverted = canBeInverted(stackPos); if (UNLIKELY(isInverted)) { - stackPos = m_currentFunction->peekByteCode(m_lastI32EqzPos)->srcOffset(); + stackPos = m_currentFunction + ->peekByteCode(m_lastI32EqzPos) + ->srcOffset(); m_currentFunction->resizeByteCode(m_lastI32EqzPos); m_lastI32EqzPos = s_noI32Eqz; } BlockInfo b(BlockInfo::IfElse, sigType, *this); - b.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJumpIf, b.m_position }); + b.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJumpIf, b.m_position }); m_blockInfo.push_back(b); if (UNLIKELY(isInverted)) { @@ -1438,7 +1578,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,30 +1591,33 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { m_functionStackSizeSoFar = blockInfo.m_functionStackSizeSoFar; } - void keepBlockResultsIfNeeds(BlockInfo& blockInfo) + void keepBlockResultsIfNeeds(BlockInfo &blockInfo) { auto dropSize = dropStackValuesBeforeBrIfNeeds(0); keepBlockResultsIfNeeds(blockInfo, dropSize); } - void keepBlockResultsIfNeeds(BlockInfo& blockInfo, const std::pair& dropSize) + void keepBlockResultsIfNeeds(BlockInfo &blockInfo, + const std::pair &dropSize) { if (blockInfo.m_shouldRestoreVMStackAtEnd) { if (!blockInfo.m_byteCodeGenerationStopped) { if (blockInfo.m_returnValueType.IsIndex()) { auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& result = ft->result(); + const auto &result = ft->result(); for (size_t i = 0; i < result.size(); i++) { ASSERT(peekVMStackValueType() == result[result.size() - i - 1]); auto info = peekVMStackInfo(); - generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), info.valueType()); + generateMoveCodeIfNeeds( + info.position(), info.nonOptimizedPosition(), info.valueType()); info.setPosition(info.nonOptimizedPosition()); popVMStack(); } } else if (blockInfo.m_returnValueType != Type::Void) { ASSERT(peekVMStackValueType() == toValueKind(blockInfo.m_returnValueType)); auto info = peekVMStackInfo(); - generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), info.valueType()); + generateMoveCodeIfNeeds(info.position(), info.nonOptimizedPosition(), + info.valueType()); info.setPosition(info.nonOptimizedPosition()); popVMStack(); } @@ -1485,14 +1628,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnElseExpr() override { m_preprocessData.seenBranch(); - BlockInfo& blockInfo = m_blockInfo.back(); + BlockInfo &blockInfo = m_blockInfo.back(); keepBlockResultsIfNeeds(blockInfo); ASSERT(blockInfo.m_blockType == BlockInfo::IfElse); blockInfo.m_jumpToEndBrInfo.erase(blockInfo.m_jumpToEndBrInfo.begin()); if (!blockInfo.m_byteCodeGenerationStopped) { - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); pushByteCode(Walrus::Jump(), WASMOpcode::ElseOpcode); } @@ -1514,7 +1659,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 +1678,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,12 +1711,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } else { if (iter->m_returnValueType.IsIndex()) { auto ft = m_result.m_functionTypes[iter->m_returnValueType]; - const auto& result = ft->result(); + const auto &result = ft->result(); for (size_t i = 0; i < result.size(); i++) { parameterSize += Walrus::valueStackAllocatedSize(result[i]); } } else if (iter->m_returnValueType != Type::Void) { - parameterSize += Walrus::valueStackAllocatedSize(toValueKind(iter->m_returnValueType)); + parameterSize += Walrus::valueStackAllocatedSize( + toValueKind(iter->m_returnValueType)); } } } @@ -1586,7 +1732,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return std::make_pair(dropValueSize, parameterSize); } - void generateMoveCodeIfNeeds(size_t srcPosition, size_t dstPosition, Walrus::Value::Type type) + void generateMoveCodeIfNeeds(size_t srcPosition, size_t dstPosition, + Walrus::Value::Type type) { if (srcPosition != dstPosition) { switch (type) { @@ -1652,7 +1799,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // reverse order copy to protect newer values remainSize = dropSize.second; while (true) { - generateMoveCodeIfNeeds(srcIter->position(), dstIter->nonOptimizedPosition(), srcIter->valueType()); + generateMoveCodeIfNeeds(srcIter->position(), + dstIter->nonOptimizedPosition(), + srcIter->valueType()); remainSize -= srcIter->stackAllocatedSize(); if (!remainSize) { break; @@ -1669,13 +1818,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { return; } auto pos = m_currentFunction->currentByteCodeSize(); - auto offsetCount = computeFunctionParameterOrResultOffsetCount(m_currentFunctionType->result()); + auto offsetCount = computeFunctionParameterOrResultOffsetCount( + m_currentFunctionType->result()); pushByteCode(Walrus::End(offsetCount), WASMOpcode::EndOpcode); - auto& result = m_currentFunctionType->result(); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * offsetCount)); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); - Walrus::End* end = m_currentFunction->peekByteCode(pos); + auto &result = m_currentFunctionType->result(); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * offsetCount)); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); + Walrus::End *end = m_currentFunction->peekByteCode(pos); size_t offsetIndex = 0; for (size_t i = 0; i < result.size(); i++) { auto type = result[result.size() - 1 - i]; @@ -1729,7 +1880,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,17 +1889,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { size_t pos = m_currentFunction->currentByteCodeSize(); auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& param = ft->param(); + const auto ¶m = ft->param(); for (size_t i = 0; i < param.size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == param[param.size() - i - 1]); auto info = m_vmStack.rbegin() + i; - generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), info->valueType()); + generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), + info->valueType()); info->setPosition(info->nonOptimizedPosition()); } } if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrOpcode); @@ -1762,7 +1916,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto stackPos = popVMStack(); bool isInverted = canBeInverted(stackPos); if (UNLIKELY(isInverted)) { - stackPos = m_currentFunction->peekByteCode(m_lastI32EqzPos)->srcOffset(); + stackPos = m_currentFunction + ->peekByteCode(m_lastI32EqzPos) + ->srcOffset(); m_currentFunction->resizeByteCode(m_lastI32EqzPos); m_lastI32EqzPos = s_noI32Eqz; } @@ -1770,23 +1926,31 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { // this case acts like return size_t pos = m_currentFunction->currentByteCodeSize(); if (UNLIKELY(isInverted)) { - pushByteCode(Walrus::JumpIfTrue(stackPos, sizeof(Walrus::JumpIfTrue) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); + pushByteCode( + Walrus::JumpIfTrue( + stackPos, sizeof(Walrus::JumpIfTrue) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), + WASMOpcode::BrIfOpcode); } else { - pushByteCode(Walrus::JumpIfFalse(stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), WASMOpcode::BrIfOpcode); + pushByteCode( + Walrus::JumpIfFalse( + stackPos, sizeof(Walrus::JumpIfFalse) + sizeof(Walrus::End) + sizeof(Walrus::ByteCodeStackOffset) * m_currentFunctionType->result().size()), + WASMOpcode::BrIfOpcode); } for (size_t i = 0; i < m_currentFunctionType->result().size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1]); } generateEndCode(); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (dropSize.second) { size_t pos = m_currentFunction->currentByteCodeSize(); @@ -1800,13 +1964,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrIfOpcode); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } } else if (blockInfo.m_blockType == BlockInfo::Loop && blockInfo.m_returnValueType.IsIndex() && m_result.m_functionTypes[blockInfo.m_returnValueType]->param().size()) { size_t pos = m_currentFunction->currentByteCodeSize(); @@ -1817,35 +1985,44 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } auto ft = m_result.m_functionTypes[blockInfo.m_returnValueType]; - const auto& param = ft->param(); + const auto ¶m = ft->param(); for (size_t i = 0; i < param.size(); i++) { ASSERT((m_vmStack.rbegin() + i)->valueType() == param[param.size() - i - 1]); auto info = m_vmStack.rbegin() + i; - generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), info->valueType()); + generateMoveCodeIfNeeds(info->position(), info->nonOptimizedPosition(), + info->valueType()); info->setPosition(info->nonOptimizedPosition()); } auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); } pushByteCode(Walrus::Jump(offset), WASMOpcode::BrIfOpcode); if (UNLIKELY(isInverted)) { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } else { - m_currentFunction->peekByteCode(pos)->setOffset(m_currentFunction->currentByteCodeSize() - pos); + m_currentFunction->peekByteCode(pos)->setOffset( + m_currentFunction->currentByteCodeSize() - pos); } } else { auto offset = (int32_t)blockInfo.m_position - (int32_t)m_currentFunction->currentByteCodeSize(); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJumpIf, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJumpIf, + m_currentFunction->currentByteCodeSize() }); } if (UNLIKELY(isInverted)) { - pushByteCode(Walrus::JumpIfFalse(stackPos, offset), WASMOpcode::BrIfOpcode); + pushByteCode(Walrus::JumpIfFalse(stackPos, offset), + WASMOpcode::BrIfOpcode); } else { - pushByteCode(Walrus::JumpIfTrue(stackPos, offset), WASMOpcode::BrIfOpcode); + pushByteCode(Walrus::JumpIfTrue(stackPos, offset), + WASMOpcode::BrIfOpcode); } } } @@ -1861,7 +2038,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,48 +2046,54 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto dropSize = dropStackValuesBeforeBrIfNeeds(depth); if (UNLIKELY(dropSize.second)) { - *(int32_t*)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; + *(int32_t *)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; OnBrExpr(depth); return; } - auto& blockInfo = findBlockInfoInBr(depth); + auto &blockInfo = findBlockInfoInBr(depth); offset = (int32_t)(blockInfo.m_position - brTableCode); if (blockInfo.m_blockType != BlockInfo::Loop) { ASSERT(blockInfo.m_blockType == BlockInfo::Block || blockInfo.m_blockType == BlockInfo::IfElse || blockInfo.m_blockType == BlockInfo::TryCatch); offset = jumpOffset; - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsBrTable, brTableCode + jumpOffset }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsBrTable, brTableCode + jumpOffset }); } - *(int32_t*)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; + *(int32_t *)(m_currentFunction->peekByteCode(brTableCode) + jumpOffset) = offset; } - virtual void OnBrTableExpr(Index numTargets, Index* targetDepths, Index defaultTargetDepth) override + virtual void OnBrTableExpr(Index numTargets, Index *targetDepths, + Index defaultTargetDepth) override { m_preprocessData.seenBranch(); ASSERT(peekVMStackValueType() == Walrus::Value::I32); auto stackPos = popVMStack(); size_t brTableCode = m_currentFunction->currentByteCodeSize(); - pushByteCode(Walrus::BrTable(stackPos, numTargets), WASMOpcode::BrTableOpcode); + pushByteCode(Walrus::BrTable(stackPos, numTargets), + WASMOpcode::BrTableOpcode); if (numTargets) { - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(int32_t) * numTargets)); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); + m_currentFunction->expandByteCode( + Walrus::ByteCode::pointerAlignedSize(sizeof(int32_t) * numTargets)); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); for (Index i = 0; i < numTargets; i++) { - emitBrTableCase(brTableCode, targetDepths[i], sizeof(Walrus::BrTable) + i * sizeof(int32_t)); + emitBrTableCase(brTableCode, targetDepths[i], + sizeof(Walrus::BrTable) + i * sizeof(int32_t)); } } // generate default - emitBrTableCase(brTableCode, defaultTargetDepth, Walrus::BrTable::offsetOfDefault()); + emitBrTableCase(brTableCode, defaultTargetDepth, + Walrus::BrTable::offsetOfDefault()); stopToGenerateByteCodeWhileBlockEnd(); } - virtual void OnSelectExpr(Index resultCount, Type* resultTypes) override + virtual void OnSelectExpr(Index resultCount, Type *resultTypes) override { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); ASSERT(resultCount == 0 || resultCount == 1); @@ -1921,7 +2104,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src0 = popVMStack(); auto dst = computeExprResultPosition(type); bool isFloat = type == Walrus::Value::F32 || type == Walrus::Value::F64; - pushByteCode(Walrus::Select(stackPos, Walrus::valueSize(type), isFloat, src0, src1, dst), WASMOpcode::SelectOpcode); + pushByteCode(Walrus::Select(stackPos, Walrus::valueSize(type), isFloat, + src0, src1, dst), + WASMOpcode::SelectOpcode); } virtual void OnThrowExpr(Index tagIndex) override @@ -1931,17 +2116,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { uint32_t offsetsSize = 0; if (tagIndex != std::numeric_limits::max()) { - offsetsSize = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]->param().size(); + offsetsSize = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()] + ->param() + .size(); } pushByteCode(Walrus::Throw(tagIndex, offsetsSize), WASMOpcode::ThrowOpcode); if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; - auto& param = functionType->param(); - m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize(sizeof(Walrus::ByteCodeStackOffset) * param.size())); - ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void*) == 0); - Walrus::Throw* code = m_currentFunction->peekByteCode(pos); + auto ¶m = functionType->param(); + m_currentFunction->expandByteCode(Walrus::ByteCode::pointerAlignedSize( + sizeof(Walrus::ByteCodeStackOffset) * param.size())); + ASSERT(m_currentFunction->currentByteCodeSize() % sizeof(void *) == 0); + Walrus::Throw *code = m_currentFunction->peekByteCode(pos); for (size_t i = 0; i < param.size(); i++) { code->dataOffsets()[param.size() - i - 1] = (m_vmStack.rbegin() + i)->position(); } @@ -1966,7 +2154,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); @@ -1977,13 +2165,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } if (!blockInfo.m_byteCodeGenerationStopped) { - blockInfo.m_jumpToEndBrInfo.push_back({ BlockInfo::JumpToEndBrInfo::IsJump, m_currentFunction->currentByteCodeSize() }); + blockInfo.m_jumpToEndBrInfo.push_back( + { BlockInfo::JumpToEndBrInfo::IsJump, + m_currentFunction->currentByteCodeSize() }); pushByteCode(Walrus::Jump(), WASMOpcode::CatchOpcode); } blockInfo.m_byteCodeGenerationStopped = false; - m_catchInfo.push_back({ m_blockInfo.size(), m_blockInfo.back().m_position, tryEnd, m_currentFunction->currentByteCodeSize(), tagIndex }); + m_catchInfo.push_back({ m_blockInfo.size(), m_blockInfo.back().m_position, + tryEnd, m_currentFunction->currentByteCodeSize(), + tagIndex }); if (tagIndex != std::numeric_limits::max()) { auto functionType = m_result.m_functionTypes[m_result.m_tagTypes[tagIndex]->sigIndex()]; @@ -2012,7 +2204,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryInit(memidx, segmentIndex, src0, src1, src2), WASMOpcode::MemoryInitOpcode); + pushByteCode(Walrus::MemoryInit(memidx, segmentIndex, src0, src1, src2), + WASMOpcode::MemoryInitOpcode); } virtual void OnMemoryCopyExpr(Index srcMemIndex, Index dstMemIndex) override @@ -2024,7 +2217,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryCopy(srcMemIndex, dstMemIndex, src0, src1, src2), WASMOpcode::MemoryCopyOpcode); + pushByteCode(Walrus::MemoryCopy(srcMemIndex, dstMemIndex, src0, src1, src2), + WASMOpcode::MemoryCopyOpcode); } virtual void OnMemoryFillExpr(Index memidx) override @@ -2036,7 +2230,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::MemoryFill(memidx, src0, src1, src2), WASMOpcode::MemoryFillOpcode); + pushByteCode(Walrus::MemoryFill(memidx, src0, src1, src2), + WASMOpcode::MemoryFillOpcode); } virtual void OnDataDropExpr(Index segmentIndex) override @@ -2049,13 +2244,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::MemoryGrow(memidx, src, dst), WASMOpcode::MemoryGrowOpcode); + pushByteCode(Walrus::MemoryGrow(memidx, src, dst), + WASMOpcode::MemoryGrowOpcode); } virtual void OnMemorySizeExpr(Index memidx) override { auto stackPos = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::MemorySize(memidx, stackPos), WASMOpcode::MemorySizeOpcode); + pushByteCode(Walrus::MemorySize(memidx, stackPos), + WASMOpcode::MemorySizeOpcode); } virtual void OnTableGetExpr(Index tableIndex) override @@ -2063,7 +2260,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); auto dst = computeExprResultPosition(m_result.m_tableTypes[tableIndex]->type()); - pushByteCode(Walrus::TableGet(tableIndex, src, dst), WASMOpcode::TableGetOpcode); + pushByteCode(Walrus::TableGet(tableIndex, src, dst), + WASMOpcode::TableGetOpcode); } virtual void OnTableSetExpr(Index tableIndex) override @@ -2072,7 +2270,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableSet(tableIndex, src0, src1), WASMOpcode::TableSetOpcode); + pushByteCode(Walrus::TableSet(tableIndex, src0, src1), + WASMOpcode::TableSetOpcode); } virtual void OnTableGrowExpr(Index tableIndex) override @@ -2082,13 +2281,15 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == m_result.m_tableTypes[tableIndex]->type()); auto src0 = popVMStack(); auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::TableGrow(tableIndex, src0, src1, dst), WASMOpcode::TableGrowOpcode); + pushByteCode(Walrus::TableGrow(tableIndex, src0, src1, dst), + WASMOpcode::TableGrowOpcode); } virtual void OnTableSizeExpr(Index tableIndex) override { auto dst = computeExprResultPosition(Walrus::Value::Type::I32); - pushByteCode(Walrus::TableSize(tableIndex, dst), WASMOpcode::TableSizeOpcode); + pushByteCode(Walrus::TableSize(tableIndex, dst), + WASMOpcode::TableSizeOpcode); } virtual void OnTableCopyExpr(Index dst_index, Index src_index) override @@ -2099,7 +2300,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableCopy(dst_index, src_index, src0, src1, src2), WASMOpcode::TableCopyOpcode); + pushByteCode(Walrus::TableCopy(dst_index, src_index, src0, src1, src2), + WASMOpcode::TableCopyOpcode); } virtual void OnTableFillExpr(Index tableIndex) override @@ -2110,7 +2312,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableFill(tableIndex, src0, src1, src2), WASMOpcode::TableFillOpcode); + pushByteCode(Walrus::TableFill(tableIndex, src0, src1, src2), + WASMOpcode::TableFillOpcode); } virtual void OnElemDropExpr(Index segmentIndex) override @@ -2126,7 +2329,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - pushByteCode(Walrus::TableInit(tableIndex, segmentIndex, src0, src1, src2), WASMOpcode::TableInitOpcode); + pushByteCode(Walrus::TableInit(tableIndex, segmentIndex, src0, src1, src2), + WASMOpcode::TableInitOpcode); } virtual void OnLoadExpr(int opcode, Index memidx, Address alignmentLog2, Address offset) override @@ -2134,7 +2338,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { auto code = static_cast(opcode); ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); if ((opcode == (int)WASMOpcode::I32LoadOpcode || opcode == (int)WASMOpcode::F32LoadOpcode) && offset == 0) { pushByteCode(Walrus::Load32(src, dst), code); } else if ((opcode == (int)WASMOpcode::I64LoadOpcode || opcode == (int)WASMOpcode::F64LoadOpcode) && offset == 0) { @@ -2144,12 +2349,17 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnStoreExpr(int opcode, Index memidx, Address alignmentLog2, Address offset) override + virtual void OnStoreExpr(int opcode, Index memidx, Address alignmentLog2, + Address offset) override { auto code = static_cast(opcode); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[1]) + == peekVMStackValueType()); auto src1 = popVMStack(); - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); + ASSERT(WASMCodeInfo::codeTypeToValueType( + g_wasmCodeInfo[opcode].m_paramTypes[0]) + == peekVMStackValueType()); auto src0 = popVMStack(); if ((opcode == (int)WASMOpcode::I32StoreOpcode || opcode == (int)WASMOpcode::F32StoreOpcode) && offset == 0) { pushByteCode(Walrus::Store32(src0, src1), code); @@ -2333,9 +2543,11 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { Walrus::ByteCodeStackOffset dst = computeExprResultPosition(toValueKind(type)); #if defined(WALRUS_32) - pushByteCode(Walrus::Const32(dst, Walrus::Value::Null), WASMOpcode::Const32Opcode); + pushByteCode(Walrus::Const32(dst, Walrus::Value::Null), + WASMOpcode::Const32Opcode); #else - pushByteCode(Walrus::Const64(dst, Walrus::Value::Null), WASMOpcode::Const64Opcode); + pushByteCode(Walrus::Const64(dst, Walrus::Value::Null), + WASMOpcode::Const64Opcode); #endif } @@ -2350,9 +2562,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { #endif } - virtual void OnNopExpr() override - { - } + virtual void OnNopExpr() override {} virtual void OnReturnExpr() override { @@ -2362,8 +2572,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void OnEndExpr() override { - // combining an i32.eqz at the end of a block followed by a JumpIf cannot be combined - // because it is possible to jump to the location after i32.eqz + // combining an i32.eqz at the end of a block followed by a JumpIf cannot be + // combined because it is possible to jump to the location after i32.eqz m_lastI32EqzPos = s_noI32Eqz; if (m_blockInfo.size()) { auto dropSize = dropStackValuesBeforeBrIfNeeds(0); @@ -2389,7 +2599,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { for (size_t i = 0; i < blockInfo.m_vmStack.size(); i++) { stackSizeToBe += m_vmStack[i].stackAllocatedSize(); } - m_currentFunction->m_catchInfo.push_back({ iter->m_tryStart, iter->m_tryEnd, iter->m_catchStart, stackSizeToBe, iter->m_tagIndex }); + m_currentFunction->m_catchInfo.push_back( + { iter->m_tryStart, iter->m_tryEnd, iter->m_catchStart, + stackSizeToBe, iter->m_tagIndex }); iter = m_catchInfo.erase(iter); } } @@ -2405,13 +2617,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]); } @@ -2423,16 +2635,20 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { for (size_t i = 0; i < blockInfo.m_jumpToEndBrInfo.size(); i++) { switch (blockInfo.m_jumpToEndBrInfo[i].m_type) { case BlockInfo::JumpToEndBrInfo::IsJump: - m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position)->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); + m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position) + ->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); break; case BlockInfo::JumpToEndBrInfo::IsJumpIf: - m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position) + m_currentFunction + ->peekByteCode( + blockInfo.m_jumpToEndBrInfo[i].m_position) ->setOffset(m_currentFunction->currentByteCodeSize() - blockInfo.m_jumpToEndBrInfo[i].m_position); break; default: ASSERT(blockInfo.m_jumpToEndBrInfo[i].m_type == BlockInfo::JumpToEndBrInfo::IsBrTable); - int32_t* offset = m_currentFunction->peekByteCode(blockInfo.m_jumpToEndBrInfo[i].m_position); + int32_t *offset = m_currentFunction->peekByteCode( + blockInfo.m_jumpToEndBrInfo[i].m_position); *offset = m_currentFunction->currentByteCodeSize() + (size_t)*offset - blockInfo.m_jumpToEndBrInfo[i].m_position; break; } @@ -2451,13 +2667,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { virtual void EndFunctionBody(Index index) override { + optimizeLocals(); m_lastI32EqzPos = s_noI32Eqz; #if !defined(NDEBUG) if (getenv("DUMP_BYTECODE") && strlen(getenv("DUMP_BYTECODE"))) { m_currentFunction->dumpByteCode(); } if (m_shouldContinueToGenerateByteCode) { - for (size_t i = 0; i < m_currentFunctionType->result().size() && m_vmStack.size(); i++) { + for (size_t i = 0; + i < m_currentFunctionType->result().size() && m_vmStack.size(); + i++) { ASSERT(popVMStackInfo().valueType() == m_currentFunctionType->result()[m_currentFunctionType->result().size() - i - 1]); } ASSERT(m_vmStack.empty()); @@ -2469,12 +2688,14 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } // SIMD Instructions - virtual void OnLoadSplatExpr(int opcode, Index memidx, Address alignment_log2, Address offset) override + virtual void OnLoadSplatExpr(int opcode, Index memidx, Address alignment_log2, + Address offset) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { #define GENERATE_LOAD_CODE_CASE(name, ...) \ case WASMOpcode::name##Opcode: { \ @@ -2489,12 +2710,14 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnLoadZeroExpr(int opcode, Index memidx, Address alignment_log2, Address offset) override + virtual void OnLoadZeroExpr(int opcode, Index memidx, Address alignment_log2, + Address offset) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { case WASMOpcode::V128Load32ZeroOpcode: { pushByteCode(Walrus::V128Load32Zero(offset, src, dst), code); @@ -2514,28 +2737,39 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { { auto code = static_cast(opcode); switch (code) { -#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ - case WASMOpcode::name##Opcode: { \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); \ - auto src = popVMStack(); \ - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); \ - pushByteCode(Walrus::name(static_cast(value), src, dst), code); \ - break; \ - } - -#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ - case WASMOpcode::name##Opcode: { \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[1]) == peekVMStackValueType()); \ - auto src1 = popVMStack(); \ - ASSERT(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_paramTypes[0]) == peekVMStackValueType()); \ - auto src0 = popVMStack(); \ - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); \ - pushByteCode(Walrus::name(static_cast(value), src0, src1, dst), code); \ - break; \ - } - - FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP(GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) - FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP(GENERATE_SIMD_REPLACE_LANE_CODE_CASE) +#define GENERATE_SIMD_EXTRACT_LANE_CODE_CASE(name, ...) \ + case WASMOpcode::name##Opcode: { \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[0]) \ + == peekVMStackValueType()); \ + auto src = popVMStack(); \ + auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_resultType)); \ + pushByteCode(Walrus::name(static_cast(value), src, dst), code); \ + break; \ + } + +#define GENERATE_SIMD_REPLACE_LANE_CODE_CASE(name, ...) \ + case WASMOpcode::name##Opcode: { \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[1]) \ + == peekVMStackValueType()); \ + auto src1 = popVMStack(); \ + ASSERT(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_paramTypes[0]) \ + == peekVMStackValueType()); \ + auto src0 = popVMStack(); \ + auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType( \ + g_wasmCodeInfo[opcode].m_resultType)); \ + pushByteCode(Walrus::name(static_cast(value), src0, src1, dst), \ + code); \ + break; \ + } + + FOR_EACH_BYTECODE_SIMD_EXTRACT_LANE_OP( + GENERATE_SIMD_EXTRACT_LANE_CODE_CASE) + FOR_EACH_BYTECODE_SIMD_REPLACE_LANE_OP( + GENERATE_SIMD_REPLACE_LANE_CODE_CASE) #undef GENERATE_SIMD_EXTRACT_LANE_CODE_CASE #undef GENERATE_SIMD_REPLACE_LANE_CODE_CASE default: @@ -2544,19 +2778,25 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdLoadLaneExpr(int opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override + virtual void OnSimdLoadLaneExpr(int opcode, Index memidx, + Address alignment_log2, Address offset, + uint64_t value) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); switch (code) { -#define GENERATE_LOAD_CODE_CASE(name, opType) \ - case WASMOpcode::name##Opcode: { \ - pushByteCode(Walrus::name(offset, src0, src1, static_cast(value), dst), code); \ - break; \ +#define GENERATE_LOAD_CODE_CASE(name, opType) \ + case WASMOpcode::name##Opcode: { \ + pushByteCode(Walrus::name(offset, src0, src1, \ + static_cast(value), \ + dst), \ + code); \ + break; \ } FOR_EACH_BYTECODE_SIMD_LOAD_LANE_OP(GENERATE_LOAD_CODE_CASE) #undef GENERATE_LOAD_CODE_CASE @@ -2565,7 +2805,9 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdStoreLaneExpr(int opcode, Index memidx, Address alignment_log2, Address offset, uint64_t value) override + virtual void OnSimdStoreLaneExpr(int opcode, Index memidx, + Address alignment_log2, Address offset, + uint64_t value) override { auto code = static_cast(opcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); @@ -2573,10 +2815,13 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { ASSERT(peekVMStackValueType() == Walrus::Value::Type::I32); auto src0 = popVMStack(); switch (code) { -#define GENERATE_STORE_CODE_CASE(name, opType) \ - case WASMOpcode::name##Opcode: { \ - pushByteCode(Walrus::name(offset, src0, src1, static_cast(value)), code); \ - break; \ +#define GENERATE_STORE_CODE_CASE(name, opType) \ + case WASMOpcode::name##Opcode: { \ + pushByteCode( \ + Walrus::name(offset, src0, src1, \ + static_cast(value)), \ + code); \ + break; \ } FOR_EACH_BYTECODE_SIMD_STORE_LANE_OP(GENERATE_STORE_CODE_CASE) #undef GENERATE_STORE_CODE_CASE @@ -2585,18 +2830,21 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - virtual void OnSimdShuffleOpExpr(int opcode, uint8_t* value) override + virtual void OnSimdShuffleOpExpr(int opcode, uint8_t *value) override { ASSERT(static_cast(opcode) == WASMOpcode::I8X16ShuffleOpcode); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src1 = popVMStack(); ASSERT(peekVMStackValueType() == Walrus::Value::Type::V128); auto src0 = popVMStack(); - auto dst = computeExprResultPosition(WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); - pushByteCode(Walrus::I8X16Shuffle(src0, src1, dst, value), WASMOpcode::I8X16ShuffleOpcode); + auto dst = computeExprResultPosition( + WASMCodeInfo::codeTypeToValueType(g_wasmCodeInfo[opcode].m_resultType)); + pushByteCode(Walrus::I8X16Shuffle(src0, src1, dst, value), + WASMOpcode::I8X16ShuffleOpcode); } - void generateBinaryCode(WASMOpcode code, size_t src0, size_t src1, size_t dst) + void generateBinaryCode(WASMOpcode code, size_t src0, size_t src1, + size_t dst) { switch (code) { #define GENERATE_BINARY_CODE_CASE(name, ...) \ @@ -2647,7 +2895,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - void generateMemoryLoadCode(WASMOpcode code, size_t offset, size_t src, size_t dst) + void generateMemoryLoadCode(WASMOpcode code, size_t offset, size_t src, + size_t dst) { switch (code) { #define GENERATE_LOAD_CODE_CASE(name, readType, writeType) \ @@ -2664,7 +2913,8 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - void generateMemoryStoreCode(WASMOpcode code, size_t offset, size_t src0, size_t src1) + void generateMemoryStoreCode(WASMOpcode code, size_t offset, size_t src0, + size_t src1) { switch (code) { #define GENERATE_STORE_CODE_CASE(name, readType, writeType) \ @@ -2680,26 +2930,1892 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate { } } - bool isBinaryOperation(WASMOpcode opcode) + 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 (opcode) { -#define GENERATE_BINARY_CODE_CASE(name, op, paramType, returnType) \ - case WASMOpcode::name##Opcode: + 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 - return true; - default: - return false; + { + 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; + } } } - Walrus::WASMParsingResult& parsingResult() { return m_result; } -}; - -} // namespace wabt - -namespace Walrus { + 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_currentFunction->m_constantDebugData.size(); j++) { + if (offsets[0] == m_currentFunction->m_constantDebugData[j].second) { + setByteCodeDestination(byteCode, constantData[j].second); + offsets[0] = SIZE_MAX; + } + if (offsets[1] == m_currentFunction->m_constantDebugData[j].second) { + setByteCodeSrc0(byteCode, constantData[j].second); + offsets[1] = SIZE_MAX; + } + if (offsets[2] == m_currentFunction->m_constantDebugData[j].second) { + setByteCodeSrc1(byteCode, constantData[j].second); + offsets[2] = SIZE_MAX; + } + if (offsets[3] == m_currentFunction->m_constantDebugData[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; + } /*else if (i == info.end && offset == offsets[0] && info.type == range.type && offsetTypes[offset] == info.type) { + info.end = range.end; + info.start = range.start; + info.originalPositions.push_back(offset); + info.free = false; + 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_currentFunction->m_constantDebugData.size(); j++) { + if (m_currentFunction->m_constantDebugData[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_currentFunction->m_constantDebugData.size(); k++) { + if (m_currentFunction->m_constantDebugData[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, {}, {} }); + } +#endif + + // variable life analysis end + } +}; // namespace wabt +} // namespace wabt + + +namespace Walrus { WASMParsingResult::WASMParsingResult() : m_seenStartAttribute(false) , m_version(0) @@ -2750,7 +4866,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 +4875,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..caa0f280c 100644 --- a/src/runtime/Module.cpp +++ b/src/runtime/Module.cpp @@ -29,6 +29,7 @@ #include "interpreter/Interpreter.h" #include "parser/WASMParser.h" #include "wasi/WASI.h" +#include namespace Walrus { @@ -442,8 +443,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 +463,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..a029abce8 100644 --- a/src/runtime/Module.h +++ b/src/runtime/Module.h @@ -17,8 +17,10 @@ #ifndef __WalrusModule__ #define __WalrusModule__ +#include "Walrus.h" #include "runtime/ObjectType.h" #include "runtime/Object.h" +#include namespace wabt { class WASMBinaryReader; @@ -182,6 +184,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 +261,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_initialization.wast b/test/basic/local_initialization.wast new file mode 100644 index 000000000..bc01c43e4 --- /dev/null +++ b/test/basic/local_initialization.wast @@ -0,0 +1,63 @@ +(module + +(func (export "br_if_cmp")(param i32 i32 i64 f32 f64)(result i32 i32 i32 i32) + block (result i32) + i32.const -1 + local.get 0 + br_if 0 + drop + local.get 1 + i32.const 100 + i32.eq + end + block (result i32) + i32.const -1 + local.get 0 + br_if 0 + drop + local.get 2 + i64.const 100 + i64.eq + end + block (result i32) + i32.const -1 + local.get 0 + br_if 0 + drop + local.get 3 + f32.const 100.0 + f32.eq + end + block (result i32) + i32.const -1 + local.get 0 + br_if 0 + drop + local.get 4 + f64.const 100.0 + f64.eq + end +) + +(func (export "test10") (param i32) (result i32) + i32.const 6 + i32.const 7 + block (result i32) + local.get 0 + local.get 0 + i32.eqz + br_if 0 + + i32.const 5 + i32.le_s + end + select +) + +) + +(assert_return (invoke "test10" (i32.const 0) ) (i32.const 7) ) +(assert_return (invoke "br_if_cmp"(i32.const 0)(i32.const 100)(i64.const 100)(f32.const 100.0)(f64.const 100.0)) + (i32.const 1)(i32.const 1)(i32.const 1)(i32.const 1)) + + diff --git a/test/basic/local_livelyness.wast b/test/basic/local_livelyness.wast new file mode 100644 index 000000000..6f656ed8a --- /dev/null +++ b/test/basic/local_livelyness.wast @@ -0,0 +1,94 @@ +(module + (func $local_zero (export "local_zero")(result i32) + (local i32) + local.get 0 + ) + + (func $local_loop1 (export "local_loop1")(result i32) + (local i32 i32 i32) + i32.const 10 + local.set 0 ;;start of 0 + + ;;start of 1 + (loop $loop + i32.const 1 + local.set 1 ;;start of 1, but inside loop + + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + i32.eqz + br_if $loop + ) + + local.get 1 ;;end of 1 + ) + + (func $local_blocks (export "local_block1")(result i32) + (local i32 i32 i32 i32 i64) + + ;;end of 2 + + local.get 4 ;; start of 4 + local.get 3 ;; start of 3 + drop + drop + + i32.const 0 + local.set 0 ;; start of 0 + + + (block $block1 + i32.const 1 + local.get 0 + i32.add + local.set 0 + + (loop $block2 + local.get 1 ;; start of 1 + i32.const 3 + i32.eq + br_if $block2 + ) + + i32.const 0 + local.get 1 + i32.add + drop + ) ;; end of 1 + + ;; end of 3, 4 + i32.const 0 + ) + + (func $local_blocks2 (export "local_block2")(param i32)(result i32) + (local i32) + + i32.const 1 + i32.const 1 + i32.sub + drop + + local.get 0 + local.tee 1 + ) + + (func $params (export "params")(param i32 i64 i32 v128)(result i32) + (local i32 i64 v128) + i32.const 0 + ) + + (func $params2 (export "params2")(param v128 i32 v128)(result i32) + i32.const 0 + ) + + +) + +(assert_return (invoke "local_zero") (i32.const 0)) +(assert_return (invoke "local_loop1") (i32.const 1)) +(assert_return (invoke "local_block1") (i32.const 0)) +(assert_return (invoke "local_block2" (i32.const 42)) (i32.const 42)) +(assert_return (invoke "params" (i32.const 1) (i64.const 2) (i32.const 3) (v128.const i64x2 4 5)) (i32.const 0)) +(assert_return (invoke "params2" (v128.const i64x2 1 2) (i32.const 3) (v128.const i64x2 4 5)) (i32.const 0)) diff --git a/test/basic/local_sets.wast b/test/basic/local_sets.wast new file mode 100644 index 000000000..afd4f986e --- /dev/null +++ b/test/basic/local_sets.wast @@ -0,0 +1,110 @@ +(module + (;(func $test (export "test")(param i32)(result i32) + (local i32 i32 i32 i64) + + local.get 0 ;; start of 0 + local.get 1 ;; start of 1 + drop + drop + + i32.const 32 + local.set 0 + + i32.const 33 + local.set 1 + + local.get 0 + local.get 1 ;; end of 1 + drop + drop + + i32.const 34 + local.set 0 ;; end of 0 + + + i32.const 1 + local.set 2 ;; start of 2 + local.get 2 ;; end of 2 + drop + + i64.const 23 + local.set 4 + local.get 4 + drop + + i32.const 0 + ) + ;) + + + (func $test2 (export "test2")(result i32) + (local i32 i32 i32 i32 i32) + + i32.const 10 + local.set 0 + (loop $outer ;; runs 10 times + + i32.const 5 + local.set 1 + (loop $inner1 ;; runs 5 times + i32.const 42 + local.set 2 + local.get 2 + drop + + local.get 1 + i32.const 1 + i32.sub + local.tee 1 + + i32.const 0 + i32.eq + br_if $inner1 + ) + + i32.const 8 + local.set 3 + (loop $inner2 ;; runs 8 times + local.get 3 + i32.const 1 + i32.sub + local.tee 3 + + i32.const 0 + i32.eq + br_if $inner2 + ) + + local.get 0 + i32.const 1 + i32.sub + local.tee 0 + + i32.const 0 + i32.eq + br_if $outer + ) + + (block $block + i32.const 99999 + local.set 4 + + i32.const 0 + i32.eqz + br_if $block + local.get 4 + + ;;junk + i32.const 0 + i32.add + i32.eqz + i32.clz + drop + ) + + i32.const 0 + ) +) + +;;(assert_return (invoke "test" (i32.const 12))(i32.const 0)) +(assert_return (invoke "test2")(i32.const 0)) diff --git a/test/basic/useless_locals.wast b/test/basic/useless_locals.wast new file mode 100644 index 000000000..a96b64083 --- /dev/null +++ b/test/basic/useless_locals.wast @@ -0,0 +1,8 @@ +(module + (func $useless_locals (export "useless_locals")(param i32)(result i32) + (local i32 i32) + i32.const 42 + ) +) + +(assert_return (invoke "useless_locals" (i32.const 222)) (i32.const 42))