WasmBinaryTypes.h (3697B)
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 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef wasm_WasmBinaryTypes_h 8 #define wasm_WasmBinaryTypes_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/CheckedInt.h" 12 #include "mozilla/Maybe.h" 13 #include "mozilla/Span.h" 14 #include "mozilla/Vector.h" 15 16 #include "js/AllocPolicy.h" 17 18 #include "wasm/WasmSerialize.h" 19 #include "wasm/WasmShareable.h" 20 21 namespace js { 22 namespace wasm { 23 24 using BytecodeSpan = mozilla::Span<const uint8_t>; 25 26 // This struct captures a range of bytecode. 27 struct BytecodeRange { 28 BytecodeRange() = default; 29 30 // Infallible constructor for when we're sure the start and size are valid. 31 BytecodeRange(uint32_t start, uint32_t size) : start(start), end(start) { 32 mozilla::CheckedUint32 checkedEnd(start); 33 checkedEnd += size; 34 MOZ_RELEASE_ASSERT(checkedEnd.isValid()); 35 end = checkedEnd.value(); 36 } 37 38 // Fallible constructor for when there could be overflow. 39 [[nodiscard]] static bool fromStartAndSize(uint32_t start, uint32_t size, 40 BytecodeRange* range) { 41 mozilla::CheckedUint32 checkedEnd(start); 42 checkedEnd += size; 43 if (!checkedEnd.isValid()) { 44 return false; 45 } 46 range->start = start; 47 range->end = checkedEnd.value(); 48 return true; 49 } 50 51 uint32_t start = 0; 52 uint32_t end = 0; 53 54 WASM_CHECK_CACHEABLE_POD(start, end); 55 56 uint32_t size() const { return end - start; } 57 58 bool isEmpty() const { return start == end; } 59 60 // Returns whether a range is a non-strict subset of this range. 61 bool contains(const BytecodeRange& other) const { 62 return other.start >= start && other.end <= end; 63 } 64 65 // Returns whether an offset is contained in this range. 66 bool containsOffset(uint32_t bytecodeOffset) const { 67 return bytecodeOffset >= start && bytecodeOffset < end; 68 } 69 70 // Compare where an offset falls relative to this range. This returns `0` if 71 // it is contained in this range, `-1` if it falls before the range, and `1` 72 // if it is after the range. 73 int compareOffset(uint32_t bytecodeOffset) const { 74 if (containsOffset(bytecodeOffset)) { 75 return 0; 76 } 77 if (bytecodeOffset < start) { 78 return -1; 79 } 80 MOZ_ASSERT(bytecodeOffset >= end); 81 return 1; 82 } 83 84 bool operator==(const BytecodeRange& rhs) const { 85 return start == rhs.start && end == rhs.end; 86 } 87 88 // Returns a range that represents `this` relative to `other`. `this` must 89 // be wholly contained in `other`, no partial overlap is allowed. 90 BytecodeRange relativeTo(const BytecodeRange& other) const { 91 MOZ_RELEASE_ASSERT(other.contains(*this)); 92 return BytecodeRange(start - other.start, size()); 93 } 94 95 // Gets the span that this range represents from a span of bytecode. 96 BytecodeSpan toSpan(BytecodeSpan bytecode) const { 97 MOZ_RELEASE_ASSERT(end <= bytecode.size()); 98 return BytecodeSpan(bytecode.begin() + start, bytecode.begin() + end); 99 } 100 101 // Gets the span that this range represents from a vector of bytecode. 102 BytecodeSpan toSpan(const ShareableBytes& bytecode) const { 103 MOZ_RELEASE_ASSERT(end <= bytecode.length()); 104 return BytecodeSpan(bytecode.begin() + start, bytecode.begin() + end); 105 } 106 }; 107 108 WASM_DECLARE_CACHEABLE_POD(BytecodeRange); 109 110 using MaybeBytecodeRange = mozilla::Maybe<BytecodeRange>; 111 using BytecodeRangeVector = 112 mozilla::Vector<BytecodeRange, 0, SystemAllocPolicy>; 113 114 } // namespace wasm 115 } // namespace js 116 117 #endif /* wasm_WasmBinaryTypes_h */