WebAssembly JS API: implement more sections
[WebKit-https.git] / Source / JavaScriptCore / wasm / WasmParser.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 #if ENABLE(WEBASSEMBLY)
29
30 #include "B3Compilation.h"
31 #include "B3Procedure.h"
32 #include "WasmFormat.h"
33 #include "WasmOps.h"
34 #include "WasmSections.h"
35 #include <wtf/LEBDecoder.h>
36 #include <wtf/StdLibExtras.h>
37 #include <wtf/text/WTFString.h>
38
39 namespace JSC { namespace Wasm {
40
41 class Parser {
42 protected:
43     Parser(const uint8_t*, size_t);
44
45     bool WARN_UNUSED_RETURN consumeCharacter(char);
46     bool WARN_UNUSED_RETURN consumeString(const char*);
47     bool WARN_UNUSED_RETURN consumeUTF8String(String&, size_t);
48
49     bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t& result);
50     bool WARN_UNUSED_RETURN parseInt7(int8_t& result);
51     bool WARN_UNUSED_RETURN parseUInt7(uint8_t& result);
52     bool WARN_UNUSED_RETURN parseUInt32(uint32_t& result);
53     bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t& result) { return WTF::LEBDecoder::decodeUInt32(m_source, m_sourceLength, m_offset, result); }
54     bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t& result) { return WTF::LEBDecoder::decodeUInt64(m_source, m_sourceLength, m_offset, result); }
55
56     bool WARN_UNUSED_RETURN parseValueType(Type& result);
57     bool WARN_UNUSED_RETURN parseExternalKind(External::Kind& result);
58
59     const uint8_t* source() const { return m_source; }
60     size_t length() const { return m_sourceLength; }
61
62     size_t m_offset = 0;
63
64 private:
65     const uint8_t* m_source;
66     size_t m_sourceLength;
67 };
68
69 ALWAYS_INLINE Parser::Parser(const uint8_t* sourceBuffer, size_t sourceLength)
70     : m_source(sourceBuffer)
71     , m_sourceLength(sourceLength)
72 {
73 }
74
75 ALWAYS_INLINE bool Parser::consumeCharacter(char c)
76 {
77     if (m_offset >= length())
78         return false;
79     if (c == source()[m_offset]) {
80         m_offset++;
81         return true;
82     }
83     return false;
84 }
85
86 ALWAYS_INLINE bool Parser::consumeString(const char* str)
87 {
88     unsigned start = m_offset;
89     if (m_offset >= length())
90         return false;
91     for (size_t i = 0; str[i]; i++) {
92         if (!consumeCharacter(str[i])) {
93             m_offset = start;
94             return false;
95         }
96     }
97     return true;
98 }
99
100 ALWAYS_INLINE bool Parser::consumeUTF8String(String& result, size_t stringLength)
101 {
102     if (stringLength == 0) {
103         result = String();
104         return true;
105     }
106     if (length() < stringLength || m_offset > length() - stringLength)
107         return false;
108     result = String::fromUTF8(static_cast<const LChar*>(&source()[m_offset]), stringLength);
109     m_offset += stringLength;
110     if (result.isEmpty())
111         return false;
112     return true;
113 }
114
115 ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
116 {
117     if (length() < 4 || m_offset > length() - 4)
118         return false;
119     result = *reinterpret_cast<const uint32_t*>(source() + m_offset);
120     m_offset += 4;
121     return true;
122 }
123
124 ALWAYS_INLINE bool Parser::parseInt7(int8_t& result)
125 {
126     if (m_offset >= length())
127         return false;
128     uint8_t v = source()[m_offset++];
129     result = (v & 0x40) ? WTF::bitwise_cast<int8_t>(uint8_t(v | 0x80)) : v;
130     return (v & 0x80) == 0;
131 }
132
133 ALWAYS_INLINE bool Parser::parseUInt7(uint8_t& result)
134 {
135     if (m_offset >= length())
136         return false;
137     result = source()[m_offset++];
138     return result < 0x80;
139 }
140
141 ALWAYS_INLINE bool Parser::parseVarUInt1(uint8_t& result)
142 {
143     uint32_t temp;
144     if (!parseVarUInt32(temp))
145         return false;
146     result = static_cast<uint8_t>(temp);
147     return temp <= 1;
148 }
149
150 ALWAYS_INLINE bool Parser::parseValueType(Type& result)
151 {
152     uint8_t value;
153     if (!parseUInt7(value))
154         return false;
155     if (value >= static_cast<uint8_t>(Type::LastValueType))
156         return false;
157     result = static_cast<Type>(value);
158     return true;
159 }
160     
161 ALWAYS_INLINE bool Parser::parseExternalKind(External::Kind& result)
162 {
163     uint8_t value;
164     if (!parseUInt7(value))
165         return false;
166     if (!External::isValid(value))
167         return false;
168     result = static_cast<External::Kind>(value);
169     return true;
170 }
171
172 } } // namespace JSC::Wasm
173
174 #endif // ENABLE(WEBASSEMBLY)