summaryrefslogtreecommitdiffstats
path: root/js/src/wasm/WasmBCStk.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/wasm/WasmBCStk.h')
-rw-r--r--js/src/wasm/WasmBCStk.h345
1 files changed, 345 insertions, 0 deletions
diff --git a/js/src/wasm/WasmBCStk.h b/js/src/wasm/WasmBCStk.h
new file mode 100644
index 0000000000..330e8abd06
--- /dev/null
+++ b/js/src/wasm/WasmBCStk.h
@@ -0,0 +1,345 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2016 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This is an INTERNAL header for Wasm baseline compiler: Wasm value stack.
+
+#ifndef wasm_wasm_baseline_stk_h
+#define wasm_wasm_baseline_stk_h
+
+#include "wasm/WasmBCDefs.h"
+#include "wasm/WasmBCRegDefs.h"
+
+namespace js {
+namespace wasm {
+
+// Value stack: stack elements
+
+struct Stk {
+ private:
+ Stk() : kind_(Unknown), i64val_(0) {}
+
+ public:
+ enum Kind {
+ // The Mem opcodes are all clustered at the beginning to
+ // allow for a quick test within sync().
+ MemI32, // 32-bit integer stack value ("offs")
+ MemI64, // 64-bit integer stack value ("offs")
+ MemF32, // 32-bit floating stack value ("offs")
+ MemF64, // 64-bit floating stack value ("offs")
+#ifdef ENABLE_WASM_SIMD
+ MemV128, // 128-bit vector stack value ("offs")
+#endif
+ MemRef, // reftype (pointer wide) stack value ("offs")
+
+ // The Local opcodes follow the Mem opcodes for a similar
+ // quick test within hasLocal().
+ LocalI32, // Local int32 var ("slot")
+ LocalI64, // Local int64 var ("slot")
+ LocalF32, // Local float32 var ("slot")
+ LocalF64, // Local double var ("slot")
+#ifdef ENABLE_WASM_SIMD
+ LocalV128, // Local v128 var ("slot")
+#endif
+ LocalRef, // Local reftype (pointer wide) var ("slot")
+
+ RegisterI32, // 32-bit integer register ("i32reg")
+ RegisterI64, // 64-bit integer register ("i64reg")
+ RegisterF32, // 32-bit floating register ("f32reg")
+ RegisterF64, // 64-bit floating register ("f64reg")
+#ifdef ENABLE_WASM_SIMD
+ RegisterV128, // 128-bit vector register ("v128reg")
+#endif
+ RegisterRef, // reftype (pointer wide) register ("refReg")
+
+ ConstI32, // 32-bit integer constant ("i32val")
+ ConstI64, // 64-bit integer constant ("i64val")
+ ConstF32, // 32-bit floating constant ("f32val")
+ ConstF64, // 64-bit floating constant ("f64val")
+#ifdef ENABLE_WASM_SIMD
+ ConstV128, // 128-bit vector constant ("v128val")
+#endif
+ ConstRef, // reftype (pointer wide) constant ("refval")
+
+ Unknown,
+ };
+
+ Kind kind_;
+
+ static const Kind MemLast = MemRef;
+ static const Kind LocalLast = LocalRef;
+
+ union {
+ RegI32 i32reg_;
+ RegI64 i64reg_;
+ RegRef refReg_;
+ RegF32 f32reg_;
+ RegF64 f64reg_;
+#ifdef ENABLE_WASM_SIMD
+ RegV128 v128reg_;
+#endif
+ int32_t i32val_;
+ int64_t i64val_;
+ intptr_t refval_;
+ float f32val_;
+ double f64val_;
+#ifdef ENABLE_WASM_SIMD
+ V128 v128val_;
+#endif
+ uint32_t slot_;
+ uint32_t offs_;
+ };
+
+ explicit Stk(RegI32 r) : kind_(RegisterI32), i32reg_(r) {}
+ explicit Stk(RegI64 r) : kind_(RegisterI64), i64reg_(r) {}
+ explicit Stk(RegRef r) : kind_(RegisterRef), refReg_(r) {}
+ explicit Stk(RegF32 r) : kind_(RegisterF32), f32reg_(r) {}
+ explicit Stk(RegF64 r) : kind_(RegisterF64), f64reg_(r) {}
+#ifdef ENABLE_WASM_SIMD
+ explicit Stk(RegV128 r) : kind_(RegisterV128), v128reg_(r) {}
+#endif
+ explicit Stk(int32_t v) : kind_(ConstI32), i32val_(v) {}
+ explicit Stk(uint32_t v) : kind_(ConstI32), i32val_(int32_t(v)) {}
+ explicit Stk(int64_t v) : kind_(ConstI64), i64val_(v) {}
+ explicit Stk(float v) : kind_(ConstF32), f32val_(v) {}
+ explicit Stk(double v) : kind_(ConstF64), f64val_(v) {}
+#ifdef ENABLE_WASM_SIMD
+ explicit Stk(V128 v) : kind_(ConstV128), v128val_(v) {}
+#endif
+ explicit Stk(Kind k, uint32_t v) : kind_(k), slot_(v) {
+ MOZ_ASSERT(k > MemLast && k <= LocalLast);
+ }
+ static Stk StkRef(intptr_t v) {
+ Stk s;
+ s.kind_ = ConstRef;
+ s.refval_ = v;
+ return s;
+ }
+ static Stk StackResult(ValType type, uint32_t offs) {
+ Kind k;
+ switch (type.kind()) {
+ case ValType::I32:
+ k = Stk::MemI32;
+ break;
+ case ValType::I64:
+ k = Stk::MemI64;
+ break;
+ case ValType::V128:
+#ifdef ENABLE_WASM_SIMD
+ k = Stk::MemV128;
+ break;
+#else
+ MOZ_CRASH("No SIMD");
+#endif
+ case ValType::F32:
+ k = Stk::MemF32;
+ break;
+ case ValType::F64:
+ k = Stk::MemF64;
+ break;
+ case ValType::Ref:
+ k = Stk::MemRef;
+ break;
+ }
+ Stk s;
+ s.setOffs(k, offs);
+ return s;
+ }
+
+ void setOffs(Kind k, uint32_t v) {
+ MOZ_ASSERT(k <= MemLast);
+ kind_ = k;
+ offs_ = v;
+ }
+
+ Kind kind() const { return kind_; }
+ bool isMem() const { return kind_ <= MemLast; }
+
+ RegI32 i32reg() const {
+ MOZ_ASSERT(kind_ == RegisterI32);
+ return i32reg_;
+ }
+ RegI64 i64reg() const {
+ MOZ_ASSERT(kind_ == RegisterI64);
+ return i64reg_;
+ }
+ RegRef refReg() const {
+ MOZ_ASSERT(kind_ == RegisterRef);
+ return refReg_;
+ }
+ RegF32 f32reg() const {
+ MOZ_ASSERT(kind_ == RegisterF32);
+ return f32reg_;
+ }
+ RegF64 f64reg() const {
+ MOZ_ASSERT(kind_ == RegisterF64);
+ return f64reg_;
+ }
+#ifdef ENABLE_WASM_SIMD
+ RegV128 v128reg() const {
+ MOZ_ASSERT(kind_ == RegisterV128);
+ return v128reg_;
+ }
+#endif
+ int32_t i32val() const {
+ MOZ_ASSERT(kind_ == ConstI32);
+ return i32val_;
+ }
+ int64_t i64val() const {
+ MOZ_ASSERT(kind_ == ConstI64);
+ return i64val_;
+ }
+ intptr_t refval() const {
+ MOZ_ASSERT(kind_ == ConstRef);
+ return refval_;
+ }
+
+ // For these two, use an out-param instead of simply returning, to
+ // use the normal stack and not the x87 FP stack (which has effect on
+ // NaNs with the signaling bit set).
+
+ void f32val(float* out) const {
+ MOZ_ASSERT(kind_ == ConstF32);
+ *out = f32val_;
+ }
+ void f64val(double* out) const {
+ MOZ_ASSERT(kind_ == ConstF64);
+ *out = f64val_;
+ }
+
+#ifdef ENABLE_WASM_SIMD
+ // For SIMD, do the same as for floats since we're using float registers to
+ // hold vectors; this is just conservative.
+ void v128val(V128* out) const {
+ MOZ_ASSERT(kind_ == ConstV128);
+ *out = v128val_;
+ }
+#endif
+
+ uint32_t slot() const {
+ MOZ_ASSERT(kind_ > MemLast && kind_ <= LocalLast);
+ return slot_;
+ }
+ uint32_t offs() const {
+ MOZ_ASSERT(isMem());
+ return offs_;
+ }
+
+#ifdef DEBUG
+ // Print a stack element (Stk) to stderr. Skip the trailing \n. Printing
+ // of the actual contents of each stack element (see case ConstI32) can be
+ // filled in on demand -- even printing just the element `kind_` fields can
+ // be very useful.
+ void showStackElem() const {
+ switch (kind_) {
+ case MemI32:
+ fprintf(stderr, "MemI32()");
+ break;
+ case MemI64:
+ fprintf(stderr, "MemI64()");
+ break;
+ case MemF32:
+ fprintf(stderr, "MemF32()");
+ break;
+ case MemF64:
+ fprintf(stderr, "MemF64()");
+ break;
+# ifdef ENABLE_WASM_SIMD
+ case MemV128:
+ fprintf(stderr, "MemV128()");
+ break;
+# endif
+ case MemRef:
+ fprintf(stderr, "MemRef()");
+ break;
+ case LocalI32:
+ fprintf(stderr, "LocalI32()");
+ break;
+ case LocalI64:
+ fprintf(stderr, "LocalI64()");
+ break;
+ case LocalF32:
+ fprintf(stderr, "LocalF32()");
+ break;
+ case LocalF64:
+ fprintf(stderr, "LocalF64()");
+ break;
+# ifdef ENABLE_WASM_SIMD
+ case LocalV128:
+ fprintf(stderr, "LocalV128()");
+ break;
+# endif
+ case LocalRef:
+ fprintf(stderr, "LocalRef()");
+ break;
+ case RegisterI32:
+ fprintf(stderr, "RegisterI32()");
+ break;
+ case RegisterI64:
+ fprintf(stderr, "RegisterI64()");
+ break;
+ case RegisterF32:
+ fprintf(stderr, "RegisterF32()");
+ break;
+ case RegisterF64:
+ fprintf(stderr, "RegisterF64()");
+ break;
+# ifdef ENABLE_WASM_SIMD
+ case RegisterV128:
+ fprintf(stderr, "RegisterV128()");
+ break;
+# endif
+ case RegisterRef:
+ fprintf(stderr, "RegisterRef()");
+ break;
+ case ConstI32:
+ fprintf(stderr, "ConstI32(%d)", (int)i32val_);
+ break;
+ case ConstI64:
+ fprintf(stderr, "ConstI64()");
+ break;
+ case ConstF32:
+ fprintf(stderr, "ConstF32()");
+ break;
+ case ConstF64:
+ fprintf(stderr, "ConstF64()");
+ break;
+# ifdef ENABLE_WASM_SIMD
+ case ConstV128:
+ fprintf(stderr, "ConstV128()");
+ break;
+# endif
+ case ConstRef:
+ fprintf(stderr, "ConstRef()");
+ break;
+ case Unknown:
+ fprintf(stderr, "Unknown()");
+ break;
+ default:
+ fprintf(stderr, "!! Stk::showStackElem !!");
+ break;
+ }
+ }
+#endif
+};
+
+using StkVector = Vector<Stk, 0, SystemAllocPolicy>;
+
+} // namespace wasm
+} // namespace js
+
+#endif // wasm_wasm_baseline_stk_h