/home/arjun/llvm-project/llvm/lib/Support/SmallVector.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements the SmallVector class. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "llvm/ADT/SmallVector.h" |
14 | | #include <cstdint> |
15 | | using namespace llvm; |
16 | | |
17 | | // Check that no bytes are wasted and everything is well-aligned. |
18 | | namespace { |
19 | | struct Struct16B { |
20 | | alignas(16) void *X; |
21 | | }; |
22 | | struct Struct32B { |
23 | | alignas(32) void *X; |
24 | | }; |
25 | | } |
26 | | static_assert(sizeof(SmallVector<void *, 0>) == |
27 | | sizeof(unsigned) * 2 + sizeof(void *), |
28 | | "wasted space in SmallVector size 0"); |
29 | | static_assert(alignof(SmallVector<Struct16B, 0>) >= alignof(Struct16B), |
30 | | "wrong alignment for 16-byte aligned T"); |
31 | | static_assert(alignof(SmallVector<Struct32B, 0>) >= alignof(Struct32B), |
32 | | "wrong alignment for 32-byte aligned T"); |
33 | | static_assert(sizeof(SmallVector<Struct16B, 0>) >= alignof(Struct16B), |
34 | | "missing padding for 16-byte aligned T"); |
35 | | static_assert(sizeof(SmallVector<Struct32B, 0>) >= alignof(Struct32B), |
36 | | "missing padding for 32-byte aligned T"); |
37 | | static_assert(sizeof(SmallVector<void *, 1>) == |
38 | | sizeof(unsigned) * 2 + sizeof(void *) * 2, |
39 | | "wasted space in SmallVector size 1"); |
40 | | |
41 | | static_assert(sizeof(SmallVector<char, 0>) == |
42 | | sizeof(void *) * 2 + sizeof(void *), |
43 | | "1 byte elements have word-sized type for size and capacity"); |
44 | | |
45 | | // Note: Moving this function into the header may cause performance regression. |
46 | | template <class Size_T> |
47 | | void SmallVectorBase<Size_T>::grow_pod(void *FirstEl, size_t MinCapacity, |
48 | 131 | size_t TSize) { |
49 | 131 | // Ensure we can fit the new capacity. |
50 | 131 | // This is only going to be applicable when the capacity is 32 bit. |
51 | 131 | if (MinCapacity > SizeTypeMax()) |
52 | 0 | report_bad_alloc_error("SmallVector capacity overflow during allocation"); |
53 | 131 | |
54 | 131 | // Ensure we can meet the guarantee of space for at least one more element. |
55 | 131 | // The above check alone will not catch the case where grow is called with a |
56 | 131 | // default MinCapacity of 0, but the current capacity cannot be increased. |
57 | 131 | // This is only going to be applicable when the capacity is 32 bit. |
58 | 131 | if (capacity() == SizeTypeMax()) |
59 | 0 | report_bad_alloc_error("SmallVector capacity unable to grow"); |
60 | 131 | |
61 | 131 | // In theory 2*capacity can overflow if the capacity is 64 bit, but the |
62 | 131 | // original capacity would never be large enough for this to be a problem. |
63 | 131 | size_t NewCapacity = 2 * capacity() + 1; // Always grow. |
64 | 131 | NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); |
65 | 131 | |
66 | 131 | void *NewElts; |
67 | 131 | if (BeginX == FirstEl) { |
68 | 128 | NewElts = safe_malloc(NewCapacity * TSize); |
69 | 128 | |
70 | 128 | // Copy the elements over. No need to run dtors on PODs. |
71 | 128 | memcpy(NewElts, this->BeginX, size() * TSize); |
72 | 128 | } else { |
73 | 3 | // If this wasn't grown from the inline copy, grow the allocated space. |
74 | 3 | NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); |
75 | 3 | } |
76 | 131 | |
77 | 131 | this->BeginX = NewElts; |
78 | 131 | this->Capacity = NewCapacity; |
79 | 131 | } _ZN4llvm15SmallVectorBaseIjE8grow_podEPvmm Line | Count | Source | 48 | 131 | size_t TSize) { | 49 | 131 | // Ensure we can fit the new capacity. | 50 | 131 | // This is only going to be applicable when the capacity is 32 bit. | 51 | 131 | if (MinCapacity > SizeTypeMax()) | 52 | 0 | report_bad_alloc_error("SmallVector capacity overflow during allocation"); | 53 | 131 | | 54 | 131 | // Ensure we can meet the guarantee of space for at least one more element. | 55 | 131 | // The above check alone will not catch the case where grow is called with a | 56 | 131 | // default MinCapacity of 0, but the current capacity cannot be increased. | 57 | 131 | // This is only going to be applicable when the capacity is 32 bit. | 58 | 131 | if (capacity() == SizeTypeMax()) | 59 | 0 | report_bad_alloc_error("SmallVector capacity unable to grow"); | 60 | 131 | | 61 | 131 | // In theory 2*capacity can overflow if the capacity is 64 bit, but the | 62 | 131 | // original capacity would never be large enough for this to be a problem. | 63 | 131 | size_t NewCapacity = 2 * capacity() + 1; // Always grow. | 64 | 131 | NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); | 65 | 131 | | 66 | 131 | void *NewElts; | 67 | 131 | if (BeginX == FirstEl) { | 68 | 128 | NewElts = safe_malloc(NewCapacity * TSize); | 69 | 128 | | 70 | 128 | // Copy the elements over. No need to run dtors on PODs. | 71 | 128 | memcpy(NewElts, this->BeginX, size() * TSize); | 72 | 128 | } else { | 73 | 3 | // If this wasn't grown from the inline copy, grow the allocated space. | 74 | 3 | NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); | 75 | 3 | } | 76 | 131 | | 77 | 131 | this->BeginX = NewElts; | 78 | 131 | this->Capacity = NewCapacity; | 79 | 131 | } |
Unexecuted instantiation: _ZN4llvm15SmallVectorBaseImE8grow_podEPvmm |
80 | | |
81 | | template class llvm::SmallVectorBase<uint32_t>; |
82 | | |
83 | | // Disable the uint64_t instantiation for 32-bit builds. |
84 | | // Both uint32_t and uint64_t instantations are needed for 64-bit builds. |
85 | | // This instantiation will never be used in 32-bit builds, and will cause |
86 | | // warnings when sizeof(Size_T) > sizeof(size_t). |
87 | | #if SIZE_MAX > UINT32_MAX |
88 | | template class llvm::SmallVectorBase<uint64_t>; |
89 | | |
90 | | // Assertions to ensure this #if stays in sync with SmallVectorSizeType. |
91 | | static_assert(sizeof(SmallVectorSizeType<char>) == sizeof(uint64_t), |
92 | | "Expected SmallVectorBase<uint64_t> variant to be in use."); |
93 | | #else |
94 | | static_assert(sizeof(SmallVectorSizeType<char>) == sizeof(uint32_t), |
95 | | "Expected SmallVectorBase<uint32_t> variant to be in use."); |
96 | | #endif |