summaryrefslogtreecommitdiff
path: root/deps/v8/src/wasm/wasm-init-expr.h
blob: fcdcd25003e4f89ef785268d231914b24b89b53d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Copyright 2021 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.

#if !V8_ENABLE_WEBASSEMBLY
#error This header should only be included if WebAssembly is enabled.
#endif  // !V8_ENABLE_WEBASSEMBLY

#ifndef V8_WASM_WASM_INIT_EXPR_H_
#define V8_WASM_WASM_INIT_EXPR_H_

#include <memory>

#include "src/wasm/value-type.h"
#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace wasm {

struct WasmModule;
class WasmFeatures;

// Representation of an constant expression. Unlike {ConstantExpression}, this
// does not use {WireBytesRef}, i.e., it does not depend on a wasm module's
// bytecode representation.
// TODO(manoskouk): Add missing kinds of expressions.
class WasmInitExpr : public ZoneObject {
 public:
  enum Operator {
    kNone,
    kGlobalGet,
    kI32Const,
    kI64Const,
    kF32Const,
    kF64Const,
    kS128Const,
    kI32Add,
    kI32Sub,
    kI32Mul,
    kI64Add,
    kI64Sub,
    kI64Mul,
    kRefNullConst,
    kRefFuncConst,
    kStructNew,
    kStructNewDefault,
    kArrayNewFixed,
    kI31New,
    kStringConst,
  };

  union Immediate {
    int32_t i32_const;
    int64_t i64_const;
    float f32_const;
    double f64_const;
    std::array<uint8_t, kSimd128Size> s128_const;
    uint32_t index;
    HeapType::Representation heap_type;
  };

  WasmInitExpr() : kind_(kNone), operands_(nullptr) {
    immediate_.i32_const = 0;
  }
  explicit WasmInitExpr(int32_t v) : kind_(kI32Const), operands_(nullptr) {
    immediate_.i32_const = v;
  }
  explicit WasmInitExpr(int64_t v) : kind_(kI64Const), operands_(nullptr) {
    immediate_.i64_const = v;
  }
  explicit WasmInitExpr(float v) : kind_(kF32Const), operands_(nullptr) {
    immediate_.f32_const = v;
  }
  explicit WasmInitExpr(double v) : kind_(kF64Const), operands_(nullptr) {
    immediate_.f64_const = v;
  }
  explicit WasmInitExpr(uint8_t v[kSimd128Size])
      : kind_(kS128Const), operands_(nullptr) {
    memcpy(immediate_.s128_const.data(), v, kSimd128Size);
  }

  static WasmInitExpr Binop(Zone* zone, Operator op, WasmInitExpr lhs,
                            WasmInitExpr rhs) {
    DCHECK(op == kI32Add || op == kI32Sub || op == kI32Mul || op == kI64Add ||
           op == kI64Sub || op == kI64Mul);
    return WasmInitExpr(
        op, zone->New<ZoneVector<WasmInitExpr>>(
                std::initializer_list<WasmInitExpr>{lhs, rhs}, zone));
  }

  static WasmInitExpr GlobalGet(uint32_t index) {
    WasmInitExpr expr;
    expr.kind_ = kGlobalGet;
    expr.immediate_.index = index;
    return expr;
  }

  static WasmInitExpr RefFuncConst(uint32_t index) {
    WasmInitExpr expr;
    expr.kind_ = kRefFuncConst;
    expr.immediate_.index = index;
    return expr;
  }

  static WasmInitExpr RefNullConst(HeapType::Representation heap_type) {
    WasmInitExpr expr;
    expr.kind_ = kRefNullConst;
    expr.immediate_.heap_type = heap_type;
    return expr;
  }

  static WasmInitExpr StructNew(uint32_t index,
                                ZoneVector<WasmInitExpr>* elements) {
    WasmInitExpr expr(kStructNew, elements);
    expr.immediate_.index = index;
    return expr;
  }

  static WasmInitExpr StructNewDefault(uint32_t index) {
    WasmInitExpr expr;
    expr.kind_ = kStructNewDefault;
    expr.immediate_.index = index;
    return expr;
  }

  static WasmInitExpr ArrayNewFixed(uint32_t index,
                                    ZoneVector<WasmInitExpr>* elements) {
    WasmInitExpr expr(kArrayNewFixed, elements);
    expr.immediate_.index = index;
    return expr;
  }

  static WasmInitExpr I31New(Zone* zone, WasmInitExpr value) {
    WasmInitExpr expr(kI31New,
                      zone->New<ZoneVector<WasmInitExpr>>(
                          std::initializer_list<WasmInitExpr>{value}, zone));
    return expr;
  }

  static WasmInitExpr StringConst(uint32_t index) {
    WasmInitExpr expr;
    expr.kind_ = kStringConst;
    expr.immediate_.index = index;
    return expr;
  }

  Immediate immediate() const { return immediate_; }
  Operator kind() const { return kind_; }
  const ZoneVector<WasmInitExpr>* operands() const { return operands_; }

  bool operator==(const WasmInitExpr& other) const {
    if (kind() != other.kind()) return false;
    switch (kind()) {
      case kNone:
        return true;
      case kGlobalGet:
      case kRefFuncConst:
      case kStringConst:
        return immediate().index == other.immediate().index;
      case kI32Const:
        return immediate().i32_const == other.immediate().i32_const;
      case kI64Const:
        return immediate().i64_const == other.immediate().i64_const;
      case kF32Const:
        return immediate().f32_const == other.immediate().f32_const;
      case kF64Const:
        return immediate().f64_const == other.immediate().f64_const;
      case kI32Add:
      case kI32Sub:
      case kI32Mul:
      case kI64Add:
      case kI64Sub:
      case kI64Mul:
        return operands_[0] == other.operands_[0] &&
               operands_[1] == other.operands_[1];
      case kS128Const:
        return immediate().s128_const == other.immediate().s128_const;
      case kRefNullConst:
        return immediate().heap_type == other.immediate().heap_type;
      case kStructNew:
      case kStructNewDefault:
        if (immediate().index != other.immediate().index) return false;
        DCHECK_EQ(operands()->size(), other.operands()->size());
        for (uint32_t i = 0; i < operands()->size(); i++) {
          if (operands()[i] != other.operands()[i]) return false;
        }
        return true;
      case kArrayNewFixed:
        if (immediate().index != other.immediate().index) return false;
        if (operands()->size() != other.operands()->size()) return false;
        for (uint32_t i = 0; i < operands()->size(); i++) {
          if (operands()[i] != other.operands()[i]) return false;
        }
        return true;
      case kI31New: {
        return operands_[0] == other.operands_[0];
      }
    }
  }

  V8_INLINE bool operator!=(const WasmInitExpr& other) const {
    return !(*this == other);
  }

  ValueType type(const WasmModule* module,
                 const WasmFeatures& enabled_features) const;

 private:
  WasmInitExpr(Operator kind, const ZoneVector<WasmInitExpr>* operands)
      : kind_(kind), operands_(operands) {}
  Immediate immediate_;
  Operator kind_;
  const ZoneVector<WasmInitExpr>* operands_;
};

ASSERT_TRIVIALLY_COPYABLE(WasmInitExpr);

}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_WASM_INIT_EXPR_H_