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 <memory>
9
10#include "src/base/compiler-specific.h"
11
12#include "src/handles.h"
13#include "src/globals.h"
14
15namespace v8 {
16namespace internal {
17
18class Isolate;
19
20namespace wasm {
21
22// Error codes for programmatic checking of the decoder's verification.
23enum ErrorCode {
24  kSuccess,
25  kError,  // TODO(titzer): introduce real error codes
26};
27
28// The overall result of decoding a function or a module.
29template <typename T>
30struct Result {
31  Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) {}
32  Result(Result&& other) { *this = std::move(other); }
33  Result& operator=(Result&& other) {
34    MoveFrom(other);
35    val = other.val;
36    return *this;
37  }
38
39  T val;
40  ErrorCode error_code;
41  const byte* start;
42  const byte* error_pc;
43  const byte* error_pt;
44  std::unique_ptr<char[]> error_msg;
45
46  bool ok() const { return error_code == kSuccess; }
47  bool failed() const { return error_code != kSuccess; }
48
49  template <typename V>
50  void MoveFrom(Result<V>& that) {
51    error_code = that.error_code;
52    start = that.start;
53    error_pc = that.error_pc;
54    error_pt = that.error_pt;
55    error_msg = std::move(that.error_msg);
56  }
57
58 private:
59  DISALLOW_COPY_AND_ASSIGN(Result);
60};
61
62template <typename T>
63std::ostream& operator<<(std::ostream& os, const Result<T>& result) {
64  os << "Result = ";
65  if (result.ok()) {
66    if (result.val != nullptr) {
67      os << *result.val;
68    } else {
69      os << "success (no value)";
70    }
71  } else if (result.error_msg.get() != nullptr) {
72    ptrdiff_t offset = result.error_pc - result.start;
73    if (offset < 0) {
74      os << result.error_msg.get() << " @" << offset;
75    } else {
76      os << result.error_msg.get() << " @+" << offset;
77    }
78  } else {
79    os << result.error_code;
80  }
81  os << std::endl;
82  return os;
83}
84
85V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
86                                           const ErrorCode& error_code);
87
88// A helper for generating error messages that bubble up to JS exceptions.
89class V8_EXPORT_PRIVATE ErrorThrower {
90 public:
91  ErrorThrower(i::Isolate* isolate, const char* context)
92      : isolate_(isolate), context_(context) {}
93  ~ErrorThrower();
94
95  PRINTF_FORMAT(2, 3) void TypeError(const char* fmt, ...);
96  PRINTF_FORMAT(2, 3) void RangeError(const char* fmt, ...);
97  PRINTF_FORMAT(2, 3) void CompileError(const char* fmt, ...);
98  PRINTF_FORMAT(2, 3) void LinkError(const char* fmt, ...);
99  PRINTF_FORMAT(2, 3) void RuntimeError(const char* fmt, ...);
100
101  template <typename T>
102  void CompileFailed(const char* error, Result<T>& result) {
103    std::ostringstream str;
104    str << error << result;
105    CompileError("%s", str.str().c_str());
106  }
107
108  i::Handle<i::Object> Reify() {
109    i::Handle<i::Object> result = exception_;
110    exception_ = i::Handle<i::Object>::null();
111    return result;
112  }
113
114  bool error() const { return !exception_.is_null(); }
115  bool wasm_error() { return wasm_error_; }
116
117 private:
118  void Format(i::Handle<i::JSFunction> constructor, const char* fmt, va_list);
119
120  i::Isolate* isolate_;
121  const char* context_;
122  i::Handle<i::Object> exception_;
123  bool wasm_error_ = false;
124};
125}  // namespace wasm
126}  // namespace internal
127}  // namespace v8
128
129#endif
130