1// Copyright 2021 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#if !V8_ENABLE_WEBASSEMBLY
6#error This header should only be included if WebAssembly is enabled.
7#endif  // !V8_ENABLE_WEBASSEMBLY
8
9#ifndef V8_WASM_WASM_INIT_EXPR_H_
10#define V8_WASM_WASM_INIT_EXPR_H_
11
12#include <memory>
13
14#include "src/wasm/value-type.h"
15#include "src/zone/zone-containers.h"
16
17namespace v8 {
18namespace internal {
19namespace wasm {
20
21struct WasmModule;
22class WasmFeatures;
23
24// Representation of an initializer expression. Unlike {ConstantExpression} in
25// wasm-module.h, this does not use {WireBytesRef}, i.e., it does not depend on
26// a wasm module's bytecode representation.
27class WasmInitExpr : public ZoneObject {
28 public:
29  enum Operator {
30    kNone,
31    kGlobalGet,
32    kI32Const,
33    kI64Const,
34    kF32Const,
35    kF64Const,
36    kS128Const,
37    kRefNullConst,
38    kRefFuncConst,
39    kStructNewWithRtt,
40    kStructNew,
41    kStructNewDefaultWithRtt,
42    kStructNewDefault,
43    kArrayInit,
44    kArrayInitStatic,
45    kRttCanon,
46  };
47
48  union Immediate {
49    int32_t i32_const;
50    int64_t i64_const;
51    float f32_const;
52    double f64_const;
53    std::array<uint8_t, kSimd128Size> s128_const;
54    uint32_t index;
55    HeapType::Representation heap_type;
56  };
57
58  WasmInitExpr() : kind_(kNone), operands_(nullptr) {
59    immediate_.i32_const = 0;
60  }
61  explicit WasmInitExpr(int32_t v) : kind_(kI32Const), operands_(nullptr) {
62    immediate_.i32_const = v;
63  }
64  explicit WasmInitExpr(int64_t v) : kind_(kI64Const), operands_(nullptr) {
65    immediate_.i64_const = v;
66  }
67  explicit WasmInitExpr(float v) : kind_(kF32Const), operands_(nullptr) {
68    immediate_.f32_const = v;
69  }
70  explicit WasmInitExpr(double v) : kind_(kF64Const), operands_(nullptr) {
71    immediate_.f64_const = v;
72  }
73  explicit WasmInitExpr(uint8_t v[kSimd128Size])
74      : kind_(kS128Const), operands_(nullptr) {
75    memcpy(immediate_.s128_const.data(), v, kSimd128Size);
76  }
77
78  static WasmInitExpr GlobalGet(uint32_t index) {
79    WasmInitExpr expr;
80    expr.kind_ = kGlobalGet;
81    expr.immediate_.index = index;
82    return expr;
83  }
84
85  static WasmInitExpr RefFuncConst(uint32_t index) {
86    WasmInitExpr expr;
87    expr.kind_ = kRefFuncConst;
88    expr.immediate_.index = index;
89    return expr;
90  }
91
92  static WasmInitExpr RefNullConst(HeapType::Representation heap_type) {
93    WasmInitExpr expr;
94    expr.kind_ = kRefNullConst;
95    expr.immediate_.heap_type = heap_type;
96    return expr;
97  }
98
99  static WasmInitExpr StructNewWithRtt(uint32_t index,
100                                       ZoneVector<WasmInitExpr>* elements) {
101    WasmInitExpr expr(kStructNewWithRtt, elements);
102    expr.immediate_.index = index;
103    return expr;
104  }
105
106  static WasmInitExpr StructNew(uint32_t index,
107                                ZoneVector<WasmInitExpr>* elements) {
108    WasmInitExpr expr(kStructNew, elements);
109    expr.immediate_.index = index;
110    return expr;
111  }
112
113  static WasmInitExpr StructNewDefaultWithRtt(Zone* zone, uint32_t index,
114                                              WasmInitExpr rtt) {
115    WasmInitExpr expr(kStructNewDefaultWithRtt,
116                      zone->New<ZoneVector<WasmInitExpr>>(
117                          std::initializer_list<WasmInitExpr>{rtt}, zone));
118    expr.immediate_.index = index;
119    return expr;
120  }
121
122  static WasmInitExpr StructNewDefault(uint32_t index) {
123    WasmInitExpr expr;
124    expr.kind_ = kStructNewDefault;
125    expr.immediate_.index = index;
126    return expr;
127  }
128
129  static WasmInitExpr ArrayInit(uint32_t index,
130                                ZoneVector<WasmInitExpr>* elements) {
131    WasmInitExpr expr(kArrayInit, elements);
132    expr.immediate_.index = index;
133    return expr;
134  }
135
136  static WasmInitExpr ArrayInitStatic(uint32_t index,
137                                      ZoneVector<WasmInitExpr>* elements) {
138    WasmInitExpr expr(kArrayInitStatic, elements);
139    expr.immediate_.index = index;
140    return expr;
141  }
142
143  static WasmInitExpr RttCanon(uint32_t index) {
144    WasmInitExpr expr;
145    expr.kind_ = kRttCanon;
146    expr.immediate_.index = index;
147    return expr;
148  }
149
150  Immediate immediate() const { return immediate_; }
151  Operator kind() const { return kind_; }
152  const ZoneVector<WasmInitExpr>* operands() const { return operands_; }
153
154  bool operator==(const WasmInitExpr& other) const {
155    if (kind() != other.kind()) return false;
156    switch (kind()) {
157      case kNone:
158        return true;
159      case kGlobalGet:
160      case kRefFuncConst:
161      case kRttCanon:
162        return immediate().index == other.immediate().index;
163      case kI32Const:
164        return immediate().i32_const == other.immediate().i32_const;
165      case kI64Const:
166        return immediate().i64_const == other.immediate().i64_const;
167      case kF32Const:
168        return immediate().f32_const == other.immediate().f32_const;
169      case kF64Const:
170        return immediate().f64_const == other.immediate().f64_const;
171      case kS128Const:
172        return immediate().s128_const == other.immediate().s128_const;
173      case kRefNullConst:
174        return immediate().heap_type == other.immediate().heap_type;
175      case kStructNewWithRtt:
176      case kStructNew:
177      case kStructNewDefaultWithRtt:
178      case kStructNewDefault:
179        if (immediate().index != other.immediate().index) return false;
180        DCHECK_EQ(operands()->size(), other.operands()->size());
181        for (uint32_t i = 0; i < operands()->size(); i++) {
182          if (operands()[i] != other.operands()[i]) return false;
183        }
184        return true;
185      case kArrayInit:
186      case kArrayInitStatic:
187        if (immediate().index != other.immediate().index) return false;
188        if (operands()->size() != other.operands()->size()) return false;
189        for (uint32_t i = 0; i < operands()->size(); i++) {
190          if (operands()[i] != other.operands()[i]) return false;
191        }
192        return true;
193    }
194  }
195
196  V8_INLINE bool operator!=(const WasmInitExpr& other) const {
197    return !(*this == other);
198  }
199
200  ValueType type(const WasmModule* module,
201                 const WasmFeatures& enabled_features) const;
202
203 private:
204  WasmInitExpr(Operator kind, const ZoneVector<WasmInitExpr>* operands)
205      : kind_(kind), operands_(operands) {}
206  Immediate immediate_;
207  Operator kind_;
208  const ZoneVector<WasmInitExpr>* operands_;
209};
210
211ASSERT_TRIVIALLY_COPYABLE(WasmInitExpr);
212
213}  // namespace wasm
214}  // namespace internal
215}  // namespace v8
216
217#endif  // V8_WASM_WASM_INIT_EXPR_H_
218