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