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#ifndef V8_WASM_RESULT_H_ 6#define V8_WASM_RESULT_H_ 7 8#include "src/base/compiler-specific.h" 9#include "src/base/smart-pointers.h" 10 11#include "src/handles.h" 12#include "src/globals.h" 13 14namespace v8 { 15namespace internal { 16 17class Isolate; 18 19namespace wasm { 20 21// Error codes for programmatic checking of the decoder's verification. 22enum ErrorCode { 23 kSuccess, 24 kError, // TODO(titzer): remove me 25 kOutOfMemory, // decoder ran out of memory 26 kEndOfCode, // end of code reached prematurely 27 kInvalidOpcode, // found invalid opcode 28 kUnreachableCode, // found unreachable code 29 kImproperContinue, // improperly nested continue 30 kImproperBreak, // improperly nested break 31 kReturnCount, // return count mismatch 32 kTypeError, // type mismatch 33 kInvalidLocalIndex, // invalid local 34 kInvalidGlobalIndex, // invalid global 35 kInvalidFunctionIndex, // invalid function 36 kInvalidMemType // invalid memory type 37}; 38 39// The overall result of decoding a function or a module. 40template <typename T> 41struct Result { 42 Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) { 43 error_msg.Reset(nullptr); 44 } 45 46 T val; 47 ErrorCode error_code; 48 const byte* start; 49 const byte* error_pc; 50 const byte* error_pt; 51 base::SmartArrayPointer<char> error_msg; 52 53 bool ok() const { return error_code == kSuccess; } 54 bool failed() const { return error_code != kSuccess; } 55 56 template <typename V> 57 void CopyFrom(Result<V>& that) { 58 error_code = that.error_code; 59 start = that.start; 60 error_pc = that.error_pc; 61 error_pt = that.error_pt; 62 error_msg = that.error_msg; 63 } 64}; 65 66template <typename T> 67std::ostream& operator<<(std::ostream& os, const Result<T>& result) { 68 os << "Result = "; 69 if (result.ok()) { 70 if (result.val != nullptr) { 71 os << *result.val; 72 } else { 73 os << "success (no value)"; 74 } 75 } else if (result.error_msg.get() != nullptr) { 76 ptrdiff_t offset = result.error_pc - result.start; 77 if (offset < 0) { 78 os << result.error_msg.get() << " @" << offset; 79 } else { 80 os << result.error_msg.get() << " @+" << offset; 81 } 82 } else { 83 os << result.error_code; 84 } 85 os << std::endl; 86 return os; 87} 88 89std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code); 90 91// A helper for generating error messages that bubble up to JS exceptions. 92class ErrorThrower { 93 public: 94 ErrorThrower(Isolate* isolate, const char* context) 95 : isolate_(isolate), context_(context) {} 96 ~ErrorThrower(); 97 98 PRINTF_FORMAT(2, 3) void Error(const char* fmt, ...); 99 100 template <typename T> 101 void Failed(const char* error, Result<T>& result) { 102 std::ostringstream str; 103 str << error << result; 104 return Error("%s", str.str().c_str()); 105 } 106 107 i::Handle<i::String> Reify() { 108 auto result = message_; 109 message_ = i::Handle<i::String>(); 110 return result; 111 } 112 113 bool error() const { return !message_.is_null(); } 114 115 private: 116 Isolate* isolate_; 117 const char* context_; 118 i::Handle<i::String> message_; 119}; 120} // namespace wasm 121} // namespace internal 122} // namespace v8 123 124#endif 125