Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/wabt/opcode.h
1 /* 2 * Copyright 2017 WebAssembly Community Group participants 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef WABT_OPCODE_H_ 18 #define WABT_OPCODE_H_ 19 20 #include <vector> 21 22 #include "wabt/common.h" 23 #include "wabt/leb128.h" 24 #include "wabt/opcode-code-table.h" 25 26 namespace wabt { 27 28 class Features; 29 30 struct Opcode { 31 // Opcode enumerations. 32 // 33 // NOTE: this enum does not match the binary encoding. 34 // 35 enum Enum : uint32_t { 36 #define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \ 37 text, decomp) \ 38 Name, 39 #include "wabt/opcode.def" 40 #undef WABT_OPCODE 41 Invalid, 42 }; 43 44 // Static opcode objects. 45 #define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \ 46 text, decomp) \ 47 static Opcode Name##_Opcode; 48 #include "wabt/opcode.def" 49 #undef WABT_OPCODE 50 51 Opcode() = default; // Provided so Opcode can be member of a union. 52 Opcode(Enum e) : enum_(e) {} 53 operator Enum() const { return enum_; } 54 55 static Opcode FromCode(uint32_t); 56 static Opcode FromCode(uint8_t prefix, uint32_t code); 57 bool HasPrefix() const { return GetInfo().prefix != 0; } 58 uint8_t GetPrefix() const { return GetInfo().prefix; } 59 uint32_t GetCode() const { return GetInfo().code; } 60 size_t GetLength() const { return GetBytes().size(); } 61 const char* GetName() const { return GetInfo().name; } 62 const char* GetDecomp() const { 63 return *GetInfo().decomp ? GetInfo().decomp : GetInfo().name; 64 } 65 Type GetResultType() const { return GetInfo().result_type; } 66 Type GetParamType1() const { return GetInfo().param_types[0]; } 67 Type GetParamType2() const { return GetInfo().param_types[1]; } 68 Type GetParamType3() const { return GetInfo().param_types[2]; } 69 Type GetParamType(int n) const { return GetInfo().param_types[n - 1]; } 70 Address GetMemorySize() const { return GetInfo().memory_size; } 71 72 // Get the byte sequence for this opcode, including prefix. 73 std::vector<uint8_t> GetBytes() const; 74 75 // Get the lane count of an extract/replace simd op. 76 uint32_t GetSimdLaneCount() const; 77 78 // Return 1 if |alignment| matches the alignment of |opcode|, or if 79 // |alignment| is WABT_USE_NATURAL_ALIGNMENT. 80 bool IsNaturallyAligned(Address alignment) const; 81 82 // If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of 83 // |opcode|, else return |alignment|. 84 Address GetAlignment(Address alignment) const; 85 86 static bool IsPrefixByte(uint8_t byte) { 87 return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix; 88 } 89 90 bool IsEnabled(const Features& features) const; 91 bool IsInvalid() const { return enum_ >= Invalid; } 92 93 private: 94 static constexpr uint32_t kMathPrefix = 0xfc; 95 static constexpr uint32_t kThreadsPrefix = 0xfe; 96 static constexpr uint32_t kSimdPrefix = 0xfd; 97 98 struct Info { 99 const char* name; 100 const char* decomp; 101 Type result_type; 102 Type param_types[3]; 103 Address memory_size; 104 uint8_t prefix; 105 uint32_t code; 106 uint32_t prefix_code; // See PrefixCode below. Used for fast lookup. 107 }; 108 109 static uint32_t PrefixCode(uint8_t prefix, uint32_t code) { 110 if (code >= (1 << MAX_OPCODE_BITS)) { 111 // Clamp to (2^bits - 1), since we know that it is an invalid code. 112 code = (1 << MAX_OPCODE_BITS) - 1; 113 } 114 return (prefix << MAX_OPCODE_BITS) | code; 115 } 116 117 // The Opcode struct only stores an enumeration (Opcode::Enum) of all valid 118 // opcodes, densely packed. We want to be able to store invalid opcodes as 119 // well, for display to the user. To encode these, we use PrefixCode() to 120 // generate a uint32_t of the prefix/code pair, then negate the value so it 121 // doesn't overlap with the valid enum values. The negation is done using 122 // `~code + 1` since prefix_code is unsigned, and MSVC warns if you use - on 123 // an unsigned value. 124 // 125 // | 0 | Opcode::Invalid | INT32_MAX+1 UINT32_MAX | 126 // |---------------|-------------------------|---------------------------| 127 // | valid opcodes | unused space | invalid opcodes | 128 // 129 static Enum EncodeInvalidOpcode(uint32_t prefix_code) { 130 Enum result = static_cast<Enum>(~prefix_code + 1); 131 assert(result >= Invalid); 132 return result; 133 } 134 135 static void DecodeInvalidOpcode(Enum e, 136 uint8_t* out_prefix, 137 uint32_t* out_code) { 138 uint32_t prefix_code = ~static_cast<uint32_t>(e) + 1; 139 *out_prefix = prefix_code >> MAX_OPCODE_BITS; 140 *out_code = prefix_code & 0xff; 141 } 142 143 Info GetInfo() const; 144 static Info infos_[]; 145 146 Enum enum_; 147 }; 148 149 // static 150 inline Opcode Opcode::FromCode(uint32_t code) { 151 return FromCode(0, code); 152 } 153 154 // static 155 inline Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) { 156 uint32_t prefix_code = PrefixCode(prefix, code); 157 158 if (WABT_LIKELY(prefix_code < WABT_ARRAY_SIZE(WabtOpcodeCodeTable))) { 159 uint32_t value = WabtOpcodeCodeTable[prefix_code]; 160 // The default value in the table is 0. That's a valid value, but only if 161 // the code is 0 (for nop). 162 if (WABT_LIKELY(value != 0 || code == 0)) { 163 return Opcode(static_cast<Enum>(value)); 164 } 165 } 166 167 return Opcode(EncodeInvalidOpcode(prefix_code)); 168 } 169 170 } // namespace wabt 171 172 #endif // WABT_OPCODE_H_