1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#if !V8_ENABLE_WEBASSEMBLY 6#error This header should only be included if WebAssembly is enabled. 7#endif // !V8_ENABLE_WEBASSEMBLY 8 9#ifndef V8_WASM_FUNCTION_BODY_DECODER_H_ 10#define V8_WASM_FUNCTION_BODY_DECODER_H_ 11 12#include "src/base/compiler-specific.h" 13#include "src/base/iterator.h" 14#include "src/common/globals.h" 15#include "src/wasm/decoder.h" 16#include "src/wasm/wasm-opcodes.h" 17#include "src/wasm/wasm-result.h" 18 19namespace v8 { 20namespace internal { 21 22class BitVector; // forward declaration 23 24namespace wasm { 25 26class WasmFeatures; 27struct WasmModule; // forward declaration of module interface. 28 29// A wrapper around the signature and bytes of a function. 30struct FunctionBody { 31 const FunctionSig* sig; // function signature 32 uint32_t offset; // offset in the module bytes, for error reporting 33 const byte* start; // start of the function body 34 const byte* end; // end of the function body 35 36 FunctionBody(const FunctionSig* sig, uint32_t offset, const byte* start, 37 const byte* end) 38 : sig(sig), offset(offset), start(start), end(end) {} 39}; 40 41enum class LoadTransformationKind : uint8_t { kSplat, kExtend, kZeroExtend }; 42 43V8_EXPORT_PRIVATE DecodeResult VerifyWasmCode(AccountingAllocator* allocator, 44 const WasmFeatures& enabled, 45 const WasmModule* module, 46 WasmFeatures* detected, 47 const FunctionBody& body); 48 49enum PrintLocals { kPrintLocals, kOmitLocals }; 50V8_EXPORT_PRIVATE 51bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body, 52 const WasmModule* module, PrintLocals print_locals); 53 54V8_EXPORT_PRIVATE 55bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body, 56 const WasmModule* module, PrintLocals print_locals, 57 std::ostream& out, 58 std::vector<int>* line_numbers = nullptr); 59 60// A simplified form of AST printing, e.g. from a debugger. 61void PrintRawWasmCode(const byte* start, const byte* end); 62 63struct BodyLocalDecls { 64 // The size of the encoded declarations. 65 uint32_t encoded_size = 0; // size of encoded declarations 66 67 ZoneVector<ValueType> type_list; 68 69 explicit BodyLocalDecls(Zone* zone) : type_list(zone) {} 70}; 71 72V8_EXPORT_PRIVATE bool DecodeLocalDecls(const WasmFeatures& enabled, 73 BodyLocalDecls* decls, 74 const WasmModule* module, 75 const byte* start, const byte* end); 76 77V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting( 78 Zone* zone, uint32_t num_locals, const byte* start, const byte* end); 79 80// Computes the length of the opcode at the given address. 81V8_EXPORT_PRIVATE unsigned OpcodeLength(const byte* pc, const byte* end); 82 83// Computes the stack effect of the opcode at the given address. 84// Returns <pop count, push count>. 85// Be cautious with control opcodes: This function only covers their immediate, 86// local stack effect (e.g. BrIf pops 1, Br pops 0). Those opcodes can have 87// non-local stack effect though, which are not covered here. 88// TODO(clemensb): This is only used by the interpreter; move there. 89V8_EXPORT_PRIVATE std::pair<uint32_t, uint32_t> StackEffect( 90 const WasmModule* module, const FunctionSig* sig, const byte* pc, 91 const byte* end); 92 93// Checks if the underlying hardware supports the Wasm SIMD proposal. 94V8_EXPORT_PRIVATE bool CheckHardwareSupportsSimd(); 95 96// A simple forward iterator for bytecodes. 97class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) { 98 // Base class for both iterators defined below. 99 class iterator_base { 100 public: 101 iterator_base& operator++() { 102 DCHECK_LT(ptr_, end_); 103 ptr_ += OpcodeLength(ptr_, end_); 104 return *this; 105 } 106 bool operator==(const iterator_base& that) { 107 return this->ptr_ == that.ptr_; 108 } 109 bool operator!=(const iterator_base& that) { 110 return this->ptr_ != that.ptr_; 111 } 112 113 protected: 114 const byte* ptr_; 115 const byte* end_; 116 iterator_base(const byte* ptr, const byte* end) : ptr_(ptr), end_(end) {} 117 }; 118 119 public: 120 // If one wants to iterate over the bytecode without looking at {pc_offset()}. 121 class opcode_iterator 122 : public iterator_base, 123 public base::iterator<std::input_iterator_tag, WasmOpcode> { 124 public: 125 WasmOpcode operator*() { 126 DCHECK_LT(ptr_, end_); 127 return static_cast<WasmOpcode>(*ptr_); 128 } 129 130 private: 131 friend class BytecodeIterator; 132 opcode_iterator(const byte* ptr, const byte* end) 133 : iterator_base(ptr, end) {} 134 }; 135 // If one wants to iterate over the instruction offsets without looking at 136 // opcodes. 137 class offset_iterator 138 : public iterator_base, 139 public base::iterator<std::input_iterator_tag, uint32_t> { 140 public: 141 uint32_t operator*() { 142 DCHECK_LT(ptr_, end_); 143 return static_cast<uint32_t>(ptr_ - start_); 144 } 145 146 private: 147 const byte* start_; 148 friend class BytecodeIterator; 149 offset_iterator(const byte* start, const byte* ptr, const byte* end) 150 : iterator_base(ptr, end), start_(start) {} 151 }; 152 153 // Create a new {BytecodeIterator}. If the {decls} pointer is non-null, 154 // assume the bytecode starts with local declarations and decode them. 155 // Otherwise, do not decode local decls. 156 BytecodeIterator(const byte* start, const byte* end, 157 BodyLocalDecls* decls = nullptr); 158 159 base::iterator_range<opcode_iterator> opcodes() { 160 return base::iterator_range<opcode_iterator>(opcode_iterator(pc_, end_), 161 opcode_iterator(end_, end_)); 162 } 163 164 base::iterator_range<offset_iterator> offsets() { 165 return base::iterator_range<offset_iterator>( 166 offset_iterator(start_, pc_, end_), 167 offset_iterator(start_, end_, end_)); 168 } 169 170 WasmOpcode current() { 171 return static_cast<WasmOpcode>( 172 read_u8<Decoder::kNoValidation>(pc_, "expected bytecode")); 173 } 174 175 void next() { 176 if (pc_ < end_) { 177 pc_ += OpcodeLength(pc_, end_); 178 if (pc_ >= end_) pc_ = end_; 179 } 180 } 181 182 bool has_next() { return pc_ < end_; } 183 184 WasmOpcode prefixed_opcode() { 185 return read_prefixed_opcode<Decoder::kNoValidation>(pc_); 186 } 187}; 188 189} // namespace wasm 190} // namespace internal 191} // namespace v8 192 193#endif // V8_WASM_FUNCTION_BODY_DECODER_H_ 194