// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_WASM_RESULT_H_ #define V8_WASM_RESULT_H_ #include "src/base/compiler-specific.h" #include "src/base/smart-pointers.h" #include "src/handles.h" #include "src/globals.h" namespace v8 { namespace internal { class Isolate; namespace wasm { // Error codes for programmatic checking of the decoder's verification. enum ErrorCode { kSuccess, kError, // TODO(titzer): remove me kOutOfMemory, // decoder ran out of memory kEndOfCode, // end of code reached prematurely kInvalidOpcode, // found invalid opcode kUnreachableCode, // found unreachable code kImproperContinue, // improperly nested continue kImproperBreak, // improperly nested break kReturnCount, // return count mismatch kTypeError, // type mismatch kInvalidLocalIndex, // invalid local kInvalidGlobalIndex, // invalid global kInvalidFunctionIndex, // invalid function kInvalidMemType // invalid memory type }; // The overall result of decoding a function or a module. template <typename T> struct Result { Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) { error_msg.Reset(nullptr); } T val; ErrorCode error_code; const byte* start; const byte* error_pc; const byte* error_pt; base::SmartArrayPointer<char> error_msg; bool ok() const { return error_code == kSuccess; } bool failed() const { return error_code != kSuccess; } template <typename V> void CopyFrom(Result<V>& that) { error_code = that.error_code; start = that.start; error_pc = that.error_pc; error_pt = that.error_pt; error_msg = that.error_msg; } }; template <typename T> std::ostream& operator<<(std::ostream& os, const Result<T>& result) { os << "Result = "; if (result.ok()) { if (result.val != nullptr) { os << *result.val; } else { os << "success (no value)"; } } else if (result.error_msg.get() != nullptr) { ptrdiff_t offset = result.error_pc - result.start; if (offset < 0) { os << result.error_msg.get() << " @" << offset; } else { os << result.error_msg.get() << " @+" << offset; } } else { os << result.error_code; } os << std::endl; return os; } std::ostream& operator<<(std::ostream& os, const ErrorCode& error_code); // A helper for generating error messages that bubble up to JS exceptions. class ErrorThrower { public: ErrorThrower(Isolate* isolate, const char* context) : isolate_(isolate), context_(context) {} ~ErrorThrower(); PRINTF_FORMAT(2, 3) void Error(const char* fmt, ...); template <typename T> void Failed(const char* error, Result<T>& result) { std::ostringstream str; str << error << result; return Error("%s", str.str().c_str()); } i::Handle<i::String> Reify() { auto result = message_; message_ = i::Handle<i::String>(); return result; } bool error() const { return !message_.is_null(); } private: Isolate* isolate_; const char* context_; i::Handle<i::String> message_; }; } // namespace wasm } // namespace internal } // namespace v8 #endif