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