| /* |
| * Copyright 2018 WebAssembly Community Group participants |
| * |
| * 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. |
| */ |
| |
| // Abstracts out operations from specific opcodes. |
| |
| #ifndef wasm_ir_abstract_h |
| #define wasm_ir_abstract_h |
| |
| #include <wasm.h> |
| |
| namespace wasm::Abstract { |
| |
| enum Op { |
| // Unary |
| Abs, |
| Neg, |
| Popcnt, |
| // Binary |
| Add, |
| Sub, |
| Mul, |
| DivU, |
| DivS, |
| RemU, |
| RemS, |
| Shl, |
| ShrU, |
| ShrS, |
| RotL, |
| RotR, |
| And, |
| Or, |
| Xor, |
| CopySign, |
| // Relational |
| EqZ, |
| Eq, |
| Ne, |
| LtS, |
| LtU, |
| LeS, |
| LeU, |
| GtS, |
| GtU, |
| GeS, |
| GeU |
| }; |
| |
| inline bool hasAnyRotateShift(BinaryOp op) { |
| return op == RotLInt32 || op == RotRInt32 || op == RotLInt64 || |
| op == RotRInt64; |
| } |
| |
| inline bool hasAnyShift(BinaryOp op) { |
| return hasAnyRotateShift(op) || op == ShlInt32 || op == ShrSInt32 || |
| op == ShrUInt32 || op == ShlInt64 || op == ShrSInt64 || |
| op == ShrUInt64; |
| } |
| |
| inline bool hasAnyReinterpret(UnaryOp op) { |
| return op == ReinterpretInt32 || op == ReinterpretInt64 || |
| op == ReinterpretFloat32 || op == ReinterpretFloat64; |
| } |
| |
| // Provide a wasm type and an abstract op and get the concrete one. For example, |
| // you can provide i32 and Add and receive the specific opcode for a 32-bit |
| // addition, AddInt32. If the op does not exist, it returns Invalid. |
| inline UnaryOp getUnary(Type type, Op op) { |
| switch (type.getBasic()) { |
| case Type::i32: { |
| switch (op) { |
| case EqZ: |
| return EqZInt32; |
| case Popcnt: |
| return PopcntInt32; |
| default: |
| return InvalidUnary; |
| } |
| break; |
| } |
| case Type::i64: { |
| switch (op) { |
| case EqZ: |
| return EqZInt64; |
| case Popcnt: |
| return PopcntInt64; |
| default: |
| return InvalidUnary; |
| } |
| break; |
| } |
| case Type::f32: { |
| switch (op) { |
| case Abs: |
| return AbsFloat32; |
| case Neg: |
| return NegFloat32; |
| default: |
| return InvalidUnary; |
| } |
| break; |
| } |
| case Type::f64: { |
| switch (op) { |
| case Abs: |
| return AbsFloat64; |
| case Neg: |
| return NegFloat64; |
| default: |
| return InvalidUnary; |
| } |
| break; |
| } |
| case Type::v128: |
| case Type::none: |
| case Type::unreachable: { |
| return InvalidUnary; |
| } |
| } |
| WASM_UNREACHABLE("invalid type"); |
| } |
| |
| inline BinaryOp getBinary(Type type, Op op) { |
| switch (type.getBasic()) { |
| case Type::i32: { |
| switch (op) { |
| case Add: |
| return AddInt32; |
| case Sub: |
| return SubInt32; |
| case Mul: |
| return MulInt32; |
| case DivU: |
| return DivUInt32; |
| case DivS: |
| return DivSInt32; |
| case RemU: |
| return RemUInt32; |
| case RemS: |
| return RemSInt32; |
| case Shl: |
| return ShlInt32; |
| case ShrU: |
| return ShrUInt32; |
| case ShrS: |
| return ShrSInt32; |
| case RotL: |
| return RotLInt32; |
| case RotR: |
| return RotRInt32; |
| case And: |
| return AndInt32; |
| case Or: |
| return OrInt32; |
| case Xor: |
| return XorInt32; |
| case Eq: |
| return EqInt32; |
| case Ne: |
| return NeInt32; |
| case LtS: |
| return LtSInt32; |
| case LtU: |
| return LtUInt32; |
| case LeS: |
| return LeSInt32; |
| case LeU: |
| return LeUInt32; |
| case GtS: |
| return GtSInt32; |
| case GtU: |
| return GtUInt32; |
| case GeS: |
| return GeSInt32; |
| case GeU: |
| return GeUInt32; |
| default: |
| return InvalidBinary; |
| } |
| break; |
| } |
| case Type::i64: { |
| switch (op) { |
| case Add: |
| return AddInt64; |
| case Sub: |
| return SubInt64; |
| case Mul: |
| return MulInt64; |
| case DivU: |
| return DivUInt64; |
| case DivS: |
| return DivSInt64; |
| case RemU: |
| return RemUInt64; |
| case RemS: |
| return RemSInt64; |
| case Shl: |
| return ShlInt64; |
| case ShrU: |
| return ShrUInt64; |
| case ShrS: |
| return ShrSInt64; |
| case RotL: |
| return RotLInt64; |
| case RotR: |
| return RotRInt64; |
| case And: |
| return AndInt64; |
| case Or: |
| return OrInt64; |
| case Xor: |
| return XorInt64; |
| case Eq: |
| return EqInt64; |
| case Ne: |
| return NeInt64; |
| case LtS: |
| return LtSInt64; |
| case LtU: |
| return LtUInt64; |
| case LeS: |
| return LeSInt64; |
| case LeU: |
| return LeUInt64; |
| case GtS: |
| return GtSInt64; |
| case GtU: |
| return GtUInt64; |
| case GeS: |
| return GeSInt64; |
| case GeU: |
| return GeUInt64; |
| default: |
| return InvalidBinary; |
| } |
| break; |
| } |
| case Type::f32: { |
| switch (op) { |
| case Add: |
| return AddFloat32; |
| case Sub: |
| return SubFloat32; |
| case Mul: |
| return MulFloat32; |
| case DivU: |
| return DivFloat32; |
| case DivS: |
| return DivFloat32; |
| case CopySign: |
| return CopySignFloat32; |
| case Eq: |
| return EqFloat32; |
| case Ne: |
| return NeFloat32; |
| default: |
| return InvalidBinary; |
| } |
| break; |
| } |
| case Type::f64: { |
| switch (op) { |
| case Add: |
| return AddFloat64; |
| case Sub: |
| return SubFloat64; |
| case Mul: |
| return MulFloat64; |
| case DivU: |
| return DivFloat64; |
| case DivS: |
| return DivFloat64; |
| case CopySign: |
| return CopySignFloat64; |
| case Eq: |
| return EqFloat64; |
| case Ne: |
| return NeFloat64; |
| default: |
| return InvalidBinary; |
| } |
| break; |
| } |
| case Type::v128: |
| case Type::none: |
| case Type::unreachable: { |
| return InvalidBinary; |
| } |
| } |
| WASM_UNREACHABLE("invalid type"); |
| } |
| |
| } // namespace wasm::Abstract |
| |
| #endif // wasm_ir_abstract_h |