tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WasmBCStk.h (9356B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 *
      4 * Copyright 2016 Mozilla Foundation
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *     http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 // This is an INTERNAL header for Wasm baseline compiler: Wasm value stack.
     20 
     21 #ifndef wasm_wasm_baseline_stk_h
     22 #define wasm_wasm_baseline_stk_h
     23 
     24 #include "wasm/WasmBCDefs.h"
     25 #include "wasm/WasmBCRegDefs.h"
     26 
     27 namespace js {
     28 namespace wasm {
     29 
     30 // Value stack: stack elements
     31 
     32 struct Stk {
     33 private:
     34  Stk() : kind_(Unknown), i64val_(0) {}
     35 
     36 public:
     37  enum Kind {
     38    // The Mem opcodes are all clustered at the beginning to
     39    // allow for a quick test within sync().
     40    MemI32,  // 32-bit integer stack value ("offs")
     41    MemI64,  // 64-bit integer stack value ("offs")
     42    MemF32,  // 32-bit floating stack value ("offs")
     43    MemF64,  // 64-bit floating stack value ("offs")
     44 #ifdef ENABLE_WASM_SIMD
     45    MemV128,  // 128-bit vector stack value ("offs")
     46 #endif
     47    MemRef,  // reftype (pointer wide) stack value ("offs")
     48 
     49    // The Local opcodes follow the Mem opcodes for a similar
     50    // quick test within hasLocal().
     51    LocalI32,  // Local int32 var ("slot")
     52    LocalI64,  // Local int64 var ("slot")
     53    LocalF32,  // Local float32 var ("slot")
     54    LocalF64,  // Local double var ("slot")
     55 #ifdef ENABLE_WASM_SIMD
     56    LocalV128,  // Local v128 var ("slot")
     57 #endif
     58    LocalRef,  // Local reftype (pointer wide) var ("slot")
     59 
     60    RegisterI32,  // 32-bit integer register ("i32reg")
     61    RegisterI64,  // 64-bit integer register ("i64reg")
     62    RegisterF32,  // 32-bit floating register ("f32reg")
     63    RegisterF64,  // 64-bit floating register ("f64reg")
     64 #ifdef ENABLE_WASM_SIMD
     65    RegisterV128,  // 128-bit vector register ("v128reg")
     66 #endif
     67    RegisterRef,  // reftype (pointer wide) register ("refReg")
     68 
     69    ConstI32,  // 32-bit integer constant ("i32val")
     70    ConstI64,  // 64-bit integer constant ("i64val")
     71    ConstF32,  // 32-bit floating constant ("f32val")
     72    ConstF64,  // 64-bit floating constant ("f64val")
     73 #ifdef ENABLE_WASM_SIMD
     74    ConstV128,  // 128-bit vector constant ("v128val")
     75 #endif
     76    ConstRef,  // reftype (pointer wide) constant ("refval")
     77 
     78    Unknown,
     79  };
     80 
     81  Kind kind_;
     82 
     83  static const Kind MemLast = MemRef;
     84  static const Kind LocalLast = LocalRef;
     85  static const Kind RegFirst = RegisterI32;
     86  static const Kind RegLast = RegisterRef;
     87 
     88  union {
     89    RegI32 i32reg_;
     90    RegI64 i64reg_;
     91    RegRef refReg_;
     92    RegF32 f32reg_;
     93    RegF64 f64reg_;
     94 #ifdef ENABLE_WASM_SIMD
     95    RegV128 v128reg_;
     96 #endif
     97    int32_t i32val_;
     98    int64_t i64val_;
     99    intptr_t refval_;
    100    float f32val_;
    101    double f64val_;
    102 #ifdef ENABLE_WASM_SIMD
    103    V128 v128val_;
    104 #endif
    105    uint32_t slot_;
    106    uint32_t offs_;
    107  };
    108 
    109  explicit Stk(RegI32 r) : kind_(RegisterI32), i32reg_(r) {}
    110  explicit Stk(RegI64 r) : kind_(RegisterI64), i64reg_(r) {}
    111  explicit Stk(RegRef r) : kind_(RegisterRef), refReg_(r) {}
    112  explicit Stk(RegF32 r) : kind_(RegisterF32), f32reg_(r) {}
    113  explicit Stk(RegF64 r) : kind_(RegisterF64), f64reg_(r) {}
    114 #ifdef ENABLE_WASM_SIMD
    115  explicit Stk(RegV128 r) : kind_(RegisterV128), v128reg_(r) {}
    116 #endif
    117  explicit Stk(int32_t v) : kind_(ConstI32), i32val_(v) {}
    118  explicit Stk(uint32_t v) : kind_(ConstI32), i32val_(int32_t(v)) {}
    119  explicit Stk(int64_t v) : kind_(ConstI64), i64val_(v) {}
    120  explicit Stk(float v) : kind_(ConstF32), f32val_(v) {}
    121  explicit Stk(double v) : kind_(ConstF64), f64val_(v) {}
    122 #ifdef ENABLE_WASM_SIMD
    123  explicit Stk(V128 v) : kind_(ConstV128), v128val_(v) {}
    124 #endif
    125  explicit Stk(Kind k, uint32_t v) : kind_(k), slot_(v) {
    126    MOZ_ASSERT(k > MemLast && k <= LocalLast);
    127  }
    128  static Stk StkRef(intptr_t v) {
    129    Stk s;
    130    s.kind_ = ConstRef;
    131    s.refval_ = v;
    132    return s;
    133  }
    134  static Stk StackResult(ValType type, uint32_t offs) {
    135    Kind k;
    136    switch (type.kind()) {
    137      case ValType::I32:
    138        k = Stk::MemI32;
    139        break;
    140      case ValType::I64:
    141        k = Stk::MemI64;
    142        break;
    143      case ValType::V128:
    144 #ifdef ENABLE_WASM_SIMD
    145        k = Stk::MemV128;
    146        break;
    147 #else
    148        MOZ_CRASH("No SIMD");
    149 #endif
    150      case ValType::F32:
    151        k = Stk::MemF32;
    152        break;
    153      case ValType::F64:
    154        k = Stk::MemF64;
    155        break;
    156      case ValType::Ref:
    157        k = Stk::MemRef;
    158        break;
    159    }
    160    Stk s;
    161    s.setOffs(k, offs);
    162    return s;
    163  }
    164 
    165  void setOffs(Kind k, uint32_t v) {
    166    MOZ_ASSERT(k <= MemLast);
    167    kind_ = k;
    168    offs_ = v;
    169  }
    170 
    171  Kind kind() const { return kind_; }
    172  bool isMem() const { return kind_ <= MemLast; }
    173  bool isReg() const { return kind_ >= RegFirst && kind_ <= RegLast; }
    174 
    175  RegI32 i32reg() const {
    176    MOZ_ASSERT(kind_ == RegisterI32);
    177    return i32reg_;
    178  }
    179  RegI64 i64reg() const {
    180    MOZ_ASSERT(kind_ == RegisterI64);
    181    return i64reg_;
    182  }
    183  RegRef refReg() const {
    184    MOZ_ASSERT(kind_ == RegisterRef);
    185    return refReg_;
    186  }
    187  RegF32 f32reg() const {
    188    MOZ_ASSERT(kind_ == RegisterF32);
    189    return f32reg_;
    190  }
    191  RegF64 f64reg() const {
    192    MOZ_ASSERT(kind_ == RegisterF64);
    193    return f64reg_;
    194  }
    195 #ifdef ENABLE_WASM_SIMD
    196  RegV128 v128reg() const {
    197    MOZ_ASSERT(kind_ == RegisterV128);
    198    return v128reg_;
    199  }
    200 #endif
    201  int32_t i32val() const {
    202    MOZ_ASSERT(kind_ == ConstI32);
    203    return i32val_;
    204  }
    205  int64_t i64val() const {
    206    MOZ_ASSERT(kind_ == ConstI64);
    207    return i64val_;
    208  }
    209  intptr_t refval() const {
    210    MOZ_ASSERT(kind_ == ConstRef);
    211    return refval_;
    212  }
    213 
    214  // For these two, use an out-param instead of simply returning, to
    215  // use the normal stack and not the x87 FP stack (which has effect on
    216  // NaNs with the signaling bit set).
    217 
    218  void f32val(float* out) const {
    219    MOZ_ASSERT(kind_ == ConstF32);
    220    *out = f32val_;
    221  }
    222  void f64val(double* out) const {
    223    MOZ_ASSERT(kind_ == ConstF64);
    224    *out = f64val_;
    225  }
    226 
    227 #ifdef ENABLE_WASM_SIMD
    228  // For SIMD, do the same as for floats since we're using float registers to
    229  // hold vectors; this is just conservative.
    230  void v128val(V128* out) const {
    231    MOZ_ASSERT(kind_ == ConstV128);
    232    *out = v128val_;
    233  }
    234 #endif
    235 
    236  uint32_t slot() const {
    237    MOZ_ASSERT(kind_ > MemLast && kind_ <= LocalLast);
    238    return slot_;
    239  }
    240  uint32_t offs() const {
    241    MOZ_ASSERT(isMem());
    242    return offs_;
    243  }
    244 
    245 #ifdef DEBUG
    246  // Print a stack element (Stk) to stderr.  Skip the trailing \n.  Printing
    247  // of the actual contents of each stack element (see case ConstI32) can be
    248  // filled in on demand -- even printing just the element `kind_` fields can
    249  // be very useful.
    250  void showStackElem() const {
    251    switch (kind_) {
    252      case MemI32:
    253        fprintf(stderr, "MemI32()");
    254        break;
    255      case MemI64:
    256        fprintf(stderr, "MemI64()");
    257        break;
    258      case MemF32:
    259        fprintf(stderr, "MemF32()");
    260        break;
    261      case MemF64:
    262        fprintf(stderr, "MemF64()");
    263        break;
    264 #  ifdef ENABLE_WASM_SIMD
    265      case MemV128:
    266        fprintf(stderr, "MemV128()");
    267        break;
    268 #  endif
    269      case MemRef:
    270        fprintf(stderr, "MemRef()");
    271        break;
    272      case LocalI32:
    273        fprintf(stderr, "LocalI32()");
    274        break;
    275      case LocalI64:
    276        fprintf(stderr, "LocalI64()");
    277        break;
    278      case LocalF32:
    279        fprintf(stderr, "LocalF32()");
    280        break;
    281      case LocalF64:
    282        fprintf(stderr, "LocalF64()");
    283        break;
    284 #  ifdef ENABLE_WASM_SIMD
    285      case LocalV128:
    286        fprintf(stderr, "LocalV128()");
    287        break;
    288 #  endif
    289      case LocalRef:
    290        fprintf(stderr, "LocalRef()");
    291        break;
    292      case RegisterI32:
    293        fprintf(stderr, "RegisterI32()");
    294        break;
    295      case RegisterI64:
    296        fprintf(stderr, "RegisterI64()");
    297        break;
    298      case RegisterF32:
    299        fprintf(stderr, "RegisterF32()");
    300        break;
    301      case RegisterF64:
    302        fprintf(stderr, "RegisterF64()");
    303        break;
    304 #  ifdef ENABLE_WASM_SIMD
    305      case RegisterV128:
    306        fprintf(stderr, "RegisterV128()");
    307        break;
    308 #  endif
    309      case RegisterRef:
    310        fprintf(stderr, "RegisterRef()");
    311        break;
    312      case ConstI32:
    313        fprintf(stderr, "ConstI32(%d)", (int)i32val_);
    314        break;
    315      case ConstI64:
    316        fprintf(stderr, "ConstI64()");
    317        break;
    318      case ConstF32:
    319        fprintf(stderr, "ConstF32()");
    320        break;
    321      case ConstF64:
    322        fprintf(stderr, "ConstF64()");
    323        break;
    324 #  ifdef ENABLE_WASM_SIMD
    325      case ConstV128:
    326        fprintf(stderr, "ConstV128()");
    327        break;
    328 #  endif
    329      case ConstRef:
    330        fprintf(stderr, "ConstRef()");
    331        break;
    332      case Unknown:
    333        fprintf(stderr, "Unknown()");
    334        break;
    335      default:
    336        fprintf(stderr, "!! Stk::showStackElem !!");
    337        break;
    338    }
    339  }
    340 #endif
    341 };
    342 
    343 using StkVector = Vector<Stk, 0, SystemAllocPolicy>;
    344 
    345 }  // namespace wasm
    346 }  // namespace js
    347 
    348 #endif  // wasm_wasm_baseline_stk_h