Add WASM support for i64 simple opcodes.
[WebKit-https.git] / Source / JavaScriptCore / wasm / WASMFunctionParser.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "WASMParser.h"
29 #include <wtf/DataLog.h>
30
31 #if ENABLE(WEBASSEMBLY)
32
33 namespace JSC {
34
35 namespace WASM {
36
37 template<typename Context>
38 class WASMFunctionParser : public WASMParser {
39 public:
40     typedef typename Context::ExpressionType ExpressionType;
41
42     WASMFunctionParser(Context&, const Vector<uint8_t>& sourceBuffer, const WASMFunctionInformation&);
43
44     bool WARN_UNUSED_RETURN parse();
45
46 private:
47     static const bool verbose = false;
48
49     bool WARN_UNUSED_RETURN parseBlock();
50     bool WARN_UNUSED_RETURN parseExpression(WASMOpType);
51     bool WARN_UNUSED_RETURN unifyControl(Vector<ExpressionType>&, unsigned level);
52
53     Optional<Vector<ExpressionType>>& stackForControlLevel(unsigned level);
54
55     Context& m_context;
56     Vector<ExpressionType> m_expressionStack;
57 };
58
59 template<typename Context>
60 WASMFunctionParser<Context>::WASMFunctionParser(Context& context, const Vector<uint8_t>& sourceBuffer, const WASMFunctionInformation& info)
61     : WASMParser(sourceBuffer, info.start, info.end)
62     , m_context(context)
63 {
64 }
65
66 template<typename Context>
67 bool WASMFunctionParser<Context>::parse()
68 {
69     uint32_t localCount;
70     if (!parseVarUInt32(localCount))
71         return false;
72
73     for (uint32_t i = 0; i < localCount; ++i) {
74         uint32_t numberOfLocalsWithType;
75         if (!parseUInt32(numberOfLocalsWithType))
76             return false;
77
78         WASMValueType typeOfLocal;
79         if (!parseValueType(typeOfLocal))
80             return false;
81
82         m_context.addLocal(typeOfLocal, numberOfLocalsWithType);
83     }
84
85     return parseBlock();
86 }
87
88 template<typename Context>
89 bool WASMFunctionParser<Context>::parseBlock()
90 {
91     while (true) {
92         uint8_t op;
93         if (!parseUInt7(op))
94             return false;
95
96         if (!parseExpression(static_cast<WASMOpType>(op))) {
97             if (verbose)
98                 dataLogLn("failed to process op:", op);
99             return false;
100         }
101
102         if (op == WASMOpType::End)
103             break;
104     }
105
106     return true;
107 }
108
109 template<typename Context>
110 bool WASMFunctionParser<Context>::parseExpression(WASMOpType op)
111 {
112     switch (op) {
113 #define CREATE_CASE(name, id, b3op) case name:
114     FOR_EACH_WASM_BINARY_OP(CREATE_CASE) {
115         ExpressionType left = m_expressionStack.takeLast();
116         ExpressionType right = m_expressionStack.takeLast();
117         ExpressionType result;
118         if (!m_context.binaryOp(static_cast<WASMBinaryOpType>(op), left, right, result))
119             return false;
120         m_expressionStack.append(result);
121         return true;
122     }
123
124     FOR_EACH_WASM_UNARY_OP(CREATE_CASE) {
125         ExpressionType arg = m_expressionStack.takeLast();
126         ExpressionType result;
127         if (!m_context.unaryOp(static_cast<WASMUnaryOpType>(op), arg, result))
128             return false;
129         m_expressionStack.append(result);
130         return true;
131     }
132 #undef CREATE_CASE
133
134     case WASMOpType::I32Const: {
135         uint32_t constant;
136         if (!parseVarUInt32(constant))
137             return false;
138         m_expressionStack.append(m_context.addConstant(WASMValueType::I32, constant));
139         return true;
140     }
141
142     case WASMOpType::Block: {
143         if (!m_context.addBlock())
144             return false;
145         return parseBlock();
146     }
147
148     case WASMOpType::Return: {
149         uint8_t returnCount;
150         if (!parseVarUInt1(returnCount))
151             return false;
152         Vector<ExpressionType, 1> returnValues;
153         if (returnCount)
154             returnValues.append(m_expressionStack.takeLast());
155
156         return m_context.addReturn(returnValues);
157     }
158
159     case WASMOpType::End:
160         return m_context.endBlock(m_expressionStack);
161
162     }
163
164     // Unknown opcode.
165     return false;
166 }
167
168 } // namespace WASM
169
170 } // namespace JSC
171
172 #endif // ENABLE(WEBASSEMBLY)