1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #if !V8_ENABLE_WEBASSEMBLY 6 #error This header should only be included if WebAssembly is enabled. 7 #endif // !V8_ENABLE_WEBASSEMBLY 8 9 #ifndef V8_WASM_LEB_HELPER_H_ 10 #define V8_WASM_LEB_HELPER_H_ 11 12 #include <cstddef> 13 #include <cstdint> 14 15 namespace v8 { 16 namespace internal { 17 namespace wasm { 18 19 constexpr size_t kPaddedVarInt32Size = 5; 20 constexpr size_t kMaxVarInt32Size = 5; 21 constexpr size_t kMaxVarInt64Size = 10; 22 23 class LEBHelper { 24 public: 25 // Write a 32-bit unsigned LEB to {dest}, updating {dest} to point after 26 // the last uint8_t written. No safety checks. write_u32v(uint8_t ** dest,uint32_t val)27 static void write_u32v(uint8_t** dest, uint32_t val) { 28 while (val >= 0x80) { 29 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 30 val >>= 7; 31 } 32 *((*dest)++) = static_cast<uint8_t>(val & 0x7F); 33 } 34 35 // Write a 32-bit signed LEB to {dest}, updating {dest} to point after 36 // the last uint8_t written. No safety checks. write_i32v(uint8_t ** dest,int32_t val)37 static void write_i32v(uint8_t** dest, int32_t val) { 38 if (val >= 0) { 39 while (val >= 0x40) { // prevent sign extension. 40 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 41 val >>= 7; 42 } 43 *((*dest)++) = static_cast<uint8_t>(val & 0xFF); 44 } else { 45 while ((val >> 6) != -1) { 46 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 47 val >>= 7; 48 } 49 *((*dest)++) = static_cast<uint8_t>(val & 0x7F); 50 } 51 } 52 53 // Write a 64-bit unsigned LEB to {dest}, updating {dest} to point after 54 // the last uint8_t written. No safety checks. write_u64v(uint8_t ** dest,uint64_t val)55 static void write_u64v(uint8_t** dest, uint64_t val) { 56 while (val >= 0x80) { 57 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 58 val >>= 7; 59 } 60 *((*dest)++) = static_cast<uint8_t>(val & 0x7F); 61 } 62 63 // Write a 64-bit signed LEB to {dest}, updating {dest} to point after 64 // the last uint8_t written. No safety checks. write_i64v(uint8_t ** dest,int64_t val)65 static void write_i64v(uint8_t** dest, int64_t val) { 66 if (val >= 0) { 67 while (val >= 0x40) { // prevent sign extension. 68 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 69 val >>= 7; 70 } 71 *((*dest)++) = static_cast<uint8_t>(val & 0xFF); 72 } else { 73 while ((val >> 6) != -1) { 74 *((*dest)++) = static_cast<uint8_t>(0x80 | (val & 0x7F)); 75 val >>= 7; 76 } 77 *((*dest)++) = static_cast<uint8_t>(val & 0x7F); 78 } 79 } 80 81 // TODO(titzer): move core logic for decoding LEBs from decoder.h to here. 82 83 // Compute the size of {val} if emitted as an LEB32. sizeof_u32v(size_t val)84 static size_t sizeof_u32v(size_t val) { 85 size_t size = 0; 86 do { 87 size++; 88 val = val >> 7; 89 } while (val > 0); 90 return size; 91 } 92 93 // Compute the size of {val} if emitted as an LEB32. sizeof_i32v(int32_t val)94 static size_t sizeof_i32v(int32_t val) { 95 size_t size = 1; 96 if (val >= 0) { 97 while (val >= 0x40) { // prevent sign extension. 98 size++; 99 val >>= 7; 100 } 101 } else { 102 while ((val >> 6) != -1) { 103 size++; 104 val >>= 7; 105 } 106 } 107 return size; 108 } 109 110 // Compute the size of {val} if emitted as an unsigned LEB64. sizeof_u64v(uint64_t val)111 static size_t sizeof_u64v(uint64_t val) { 112 size_t size = 0; 113 do { 114 size++; 115 val = val >> 7; 116 } while (val > 0); 117 return size; 118 } 119 120 // Compute the size of {val} if emitted as a signed LEB64. sizeof_i64v(int64_t val)121 static size_t sizeof_i64v(int64_t val) { 122 size_t size = 1; 123 if (val >= 0) { 124 while (val >= 0x40) { // prevent sign extension. 125 size++; 126 val >>= 7; 127 } 128 } else { 129 while ((val >> 6) != -1) { 130 size++; 131 val >>= 7; 132 } 133 } 134 return size; 135 } 136 }; 137 138 } // namespace wasm 139 } // namespace internal 140 } // namespace v8 141 142 #endif // V8_WASM_LEB_HELPER_H_ 143