llvm.org GIT mirror llvm / 784545f
[ADT][CMake][AutoConf] Fail-fast iterators for DenseMap Summary: This patch is an attempt at making `DenseMapIterator`s "fail-fast". Fail-fast iterators that have been invalidated due to insertion into the host `DenseMap` deterministically trip an assert (in debug mode) on access, instead of non-deterministically hitting memory corruption issues. Enabling fail-fast iterators breaks the LLVM C++ ABI, so they are predicated on `LLVM_ENABLE_ABI_BREAKING_CHECKS`. `LLVM_ENABLE_ABI_BREAKING_CHECKS` by default flips with `LLVM_ENABLE_ASSERTS`, but can be clamped to ON or OFF using the CMake / autoconf build system. Reviewers: chandlerc, dexonsmith, rnk, zturner Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D8351 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233310 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjoy Das 4 years ago
11 changed file(s) with 241 addition(s) and 20 deletion(s). Raw diff Collapse all Expand all
251251 option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON)
252252 endif()
253253
254 set(LLVM_ABI_BREAKING_CHECKS "WITH_ASSERTS" CACHE STRING
255 "Enable abi-breaking checks. Can be WITH_ASSERTS, FORCE_ON or FORCE_OFF.")
256
254257 option(LLVM_FORCE_USE_OLD_HOST_TOOLCHAIN
255258 "Set to ON to force using an old, unsupported host toolchain." OFF)
256259
700700 --enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes")
701701 if test ${enableval} = "yes" ; then
702702 AC_SUBST(DISABLE_ASSERTIONS,[[]])
703 assertions_enabled="yes"
703704 else
704705 AC_SUBST(DISABLE_ASSERTIONS,[[DISABLE_ASSERTIONS=1]])
706 assertions_enabled="no"
705707 fi
706708
707709 dnl --enable-werror : check whether we want Werror on by default
724726 AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[]])
725727 AC_SUBST(EXPENSIVE_CHECKS,[[no]])
726728 fi
729
730 dnl --enable-abi-breaking-checks : decide whether we should compile in asserts and
731 dnl checks that make the build ABI incompatible with an llvm built without these
732 dnl checks enabled.
733 AC_ARG_ENABLE(abi-breaking-checks,AS_HELP_STRING(
734 --enable-abi-breaking-checks,[Compile with abi-breaking asserts support (default is with-asserts)]),, enableval="with-asserts")
735 case "$enableval" in
736 with-asserts) if test ${assertions_enabled} = "yes" ; then
737 AC_DEFINE([LLVM_ENABLE_ABI_BREAKING_CHECKS],[1],[Define to enable checks that alter the LLVM C++ ABI])
738 fi ;;
739 yes) AC_DEFINE([LLVM_ENABLE_ABI_BREAKING_CHECKS],[1],[Define to enable checks that alter the LLVM C++ ABI]) ;;
740 no) ;;
741 *) AC_MSG_ERROR([Invalid setting for --enable-abi-breaking-checks. Use "with-asserts", "yes" or "no"])
742 esac
727743
728744 dnl --enable-debug-runtime : should runtime libraries have debug symbols?
729745 AC_ARG_ENABLE(debug-runtime,
7575 "${flags_var_to_scrub}" "${${flags_var_to_scrub}}")
7676 endforeach()
7777 endif()
78 endif()
79
80 string(TOUPPER "${LLVM_ABI_BREAKING_CHECKS}" uppercase_LLVM_ABI_BREAKING_CHECKS)
81
82 if( uppercase_LLVM_ABI_BREAKING_CHECKS STREQUAL "WITH_ASSERTS" )
83 if( LLVM_ENABLE_ASSERTIONS )
84 set( LLVM_ENABLE_ABI_BREAKING_CHECKS 1 )
85 endif()
86 elseif( uppercase_LLVM_ABI_BREAKING_CHECKS STREQUAL "FORCE_ON" )
87 set( LLVM_ENABLE_ABI_BREAKING_CHECKS 1 )
88 elseif( uppercase_LLVM_ABI_BREAKING_CHECKS STREQUAL "FORCE_OFF" )
89 # We don't need to do anything special to turn off ABI breaking checks.
90 else()
91 message(FATAL_ERROR "Unknown value for LLVM_ABI_BREAKING_CHECKS: \"${LLVM_ABI_BREAKING_CHECKS}\"!")
7892 endif()
7993
8094 if(WIN32)
14251425 --enable-expensive-checks
14261426 Compile with expensive debug checks enabled (default
14271427 is NO)
1428 --enable-abi-breaking-checks
1429 Compile with abi-breaking asserts support (default
1430 is with-asserts)
14281431 --enable-debug-runtime Build runtime libs with debug symbols (default is
14291432 NO)
14301433 --enable-debug-symbols Build compiler with debug symbols (default is NO if
49794982 if test ${enableval} = "yes" ; then
49804983 DISABLE_ASSERTIONS=
49814984
4985 assertions_enabled="yes"
49824986 else
49834987 DISABLE_ASSERTIONS=DISABLE_ASSERTIONS=1
49844988
4989 assertions_enabled="no"
49854990 fi
49864991
49874992 # Check whether --enable-werror was given.
50215026 EXPENSIVE_CHECKS=no
50225027
50235028 fi
5029
5030 # Check whether --enable-abi-breaking-checks was given.
5031 if test "${enable_abi_breaking_checks+set}" = set; then
5032 enableval=$enable_abi_breaking_checks;
5033 else
5034 enableval="with-asserts"
5035 fi
5036
5037 case "$enableval" in
5038 with-asserts) if test ${assertions_enabled} = "yes" ; then
5039
5040 cat >>confdefs.h <<\_ACEOF
5041 #define LLVM_ENABLE_ABI_BREAKING_CHECKS 1
5042 _ACEOF
5043
5044 fi ;;
5045 yes)
5046 cat >>confdefs.h <<\_ACEOF
5047 #define LLVM_ENABLE_ABI_BREAKING_CHECKS 1
5048 _ACEOF
5049 ;;
5050 no) ;;
5051 *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-abi-breaking-checks. Use \"with-asserts\", \"yes\" or \"no\"" >&5
5052 echo "$as_me: error: Invalid setting for --enable-abi-breaking-checks. Use \"with-asserts\", \"yes\" or \"no\"" >&2;}
5053 { (exit 1); exit 1; }; }
5054 esac
50245055
50255056 # Check whether --enable-debug-runtime was given.
50265057 if test "${enable_debug_runtime+set}" = set; then
268268
269269 **LLVM_ENABLE_WERROR**:BOOL
270270 Stop and fail build, if a compiler warning is triggered. Defaults to OFF.
271
272 **LLVM_ABI_BREAKING_CHECKS**:STRING
273 Used to decide if LLVM should be built with ABI breaking checks or
274 not. Allowed values are `WITH_ASSERTS` (default), `FORCE_ON` and
275 `FORCE_OFF`. `WITH_ASSERTS` turns on ABI breaking checks in an
276 assertion enabled build. `FORCE_ON` (`FORCE_OFF`) turns them on
277 (off) irrespective of whether normal (`NDEBUG` based) assertions are
278 enabled or not. A version of LLVM built with ABI breaking checks
279 is not ABI compatible with a version built without it.
271280
272281 **LLVM_BUILD_32_BITS**:BOOL
273282 Build 32-bits executables and libraries on 64-bits systems. This option is
25522552 ` which describes how you can implement this
25532553 pattern for use with the LLVM helpers.
25542554
2555 .. _abi_breaking_checks:
2556
2557 ABI Breaking Checks
2558 -------------------
2559
2560 Checks and asserts that alter the LLVM C++ ABI are predicated on the
2561 preprocessor symbol `LLVM_ENABLE_ABI_BREAKING_CHECKS` -- LLVM
2562 libraries built with `LLVM_ENABLE_ABI_BREAKING_CHECKS` are not ABI
2563 compatible LLVM libraries built without it defined. By default,
2564 turning on assertions also turns on `LLVM_ENABLE_ABI_BREAKING_CHECKS`
2565 so a default +Asserts build is not ABI compatible with a
2566 default -Asserts build. Clients that want ABI compatibility
2567 between +Asserts and -Asserts builds should use the CMake or autoconf
2568 build systems to set `LLVM_ENABLE_ABI_BREAKING_CHECKS` independently
2569 of `LLVM_ENABLE_ASSERTIONS`.
2570
25552571 .. _coreclasses:
25562572
25572573 The Core LLVM Class Hierarchy Reference
1414 #define LLVM_ADT_DENSEMAP_H
1515
1616 #include "llvm/ADT/DenseMapInfo.h"
17 #include "llvm/ADT/EpochTracker.h"
1718 #include "llvm/Support/AlignOf.h"
1819 #include "llvm/Support/Compiler.h"
1920 #include "llvm/Support/MathExtras.h"
4950
5051 template
5152 typename BucketT>
52 class DenseMapBase {
53 class DenseMapBase : public DebugEpochBase {
5354 public:
5455 typedef unsigned size_type;
5556 typedef KeyT key_type;
6162 const_iterator;
6263 inline iterator begin() {
6364 // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
64 return empty() ? end() : iterator(getBuckets(), getBucketsEnd());
65 return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
6566 }
6667 inline iterator end() {
67 return iterator(getBucketsEnd(), getBucketsEnd(), true);
68 return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
6869 }
6970 inline const_iterator begin() const {
70 return empty() ? end() : const_iterator(getBuckets(), getBucketsEnd());
71 return empty() ? end()
72 : const_iterator(getBuckets(), getBucketsEnd(), *this);
7173 }
7274 inline const_iterator end() const {
73 return const_iterator(getBucketsEnd(), getBucketsEnd(), true);
75 return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
7476 }
7577
7678 bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const {
8082
8183 /// Grow the densemap so that it has at least Size buckets. Does not shrink
8284 void resize(size_type Size) {
85 incrementEpoch();
8386 if (Size > getNumBuckets())
8487 grow(Size);
8588 }
8689
8790 void clear() {
91 incrementEpoch();
8892 if (getNumEntries() == 0 && getNumTombstones() == 0) return;
8993
9094 // If the capacity of the array is huge, and the # elements used is small,
117121 iterator find(const KeyT &Val) {
118122 BucketT *TheBucket;
119123 if (LookupBucketFor(Val, TheBucket))
120 return iterator(TheBucket, getBucketsEnd(), true);
124 return iterator(TheBucket, getBucketsEnd(), *this, true);
121125 return end();
122126 }
123127 const_iterator find(const KeyT &Val) const {
124128 const BucketT *TheBucket;
125129 if (LookupBucketFor(Val, TheBucket))
126 return const_iterator(TheBucket, getBucketsEnd(), true);
130 return const_iterator(TheBucket, getBucketsEnd(), *this, true);
127131 return end();
128132 }
129133
136140 iterator find_as(const LookupKeyT &Val) {
137141 BucketT *TheBucket;
138142 if (LookupBucketFor(Val, TheBucket))
139 return iterator(TheBucket, getBucketsEnd(), true);
143 return iterator(TheBucket, getBucketsEnd(), *this, true);
140144 return end();
141145 }
142146 template
143147 const_iterator find_as(const LookupKeyT &Val) const {
144148 const BucketT *TheBucket;
145149 if (LookupBucketFor(Val, TheBucket))
146 return const_iterator(TheBucket, getBucketsEnd(), true);
150 return const_iterator(TheBucket, getBucketsEnd(), *this, true);
147151 return end();
148152 }
149153
162166 std::pair insert(const std::pair &KV) {
163167 BucketT *TheBucket;
164168 if (LookupBucketFor(KV.first, TheBucket))
165 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
169 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
166170 false); // Already in map.
167171
168172 // Otherwise, insert the new element.
169173 TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket);
170 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
174 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
175 true);
171176 }
172177
173178 // Inserts key,value pair into the map if the key isn't already in the map.
176181 std::pair insert(std::pair &&KV) {
177182 BucketT *TheBucket;
178183 if (LookupBucketFor(KV.first, TheBucket))
179 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true),
184 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
180185 false); // Already in map.
181
186
182187 // Otherwise, insert the new element.
183188 TheBucket = InsertIntoBucket(std::move(KV.first),
184189 std::move(KV.second),
185190 TheBucket);
186 return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true);
191 return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
192 true);
187193 }
188194
189195 /// insert - Range insertion of pairs.
430436 }
431437
432438 BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) {
439 incrementEpoch();
440
433441 // If the load of the hash table is more than 3/4, or if fewer than 1/8 of
434442 // the buckets are empty (meaning that many are filled with tombstones),
435443 // grow the table.
986994
987995 template
988996 bool IsConst>
989 class DenseMapIterator {
997 class DenseMapIterator : DebugEpochBase::HandleBase {
990998 typedef DenseMapIterator ConstIterator;
991999 friend class DenseMapIterator;
1000 friend class DenseMapIterator;
9921001
9931002 public:
9941003 typedef ptrdiff_t difference_type;
10021011 public:
10031012 DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
10041013
1005 DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false)
1006 : Ptr(Pos), End(E) {
1014 DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
1015 bool NoAdvance = false)
1016 : DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
1017 assert(isHandleInSync() && "invalid construction!");
10071018 if (!NoAdvance) AdvancePastEmptyBuckets();
10081019 }
10091020
10141025 typename = typename std::enable_if::type>
10151026 DenseMapIterator(
10161027 const DenseMapIterator &I)
1017 : Ptr(I.Ptr), End(I.End) {}
1028 : DebugEpochBase::HandleBase(I), Ptr(I.Ptr), End(I.End) {}
10181029
10191030 reference operator*() const {
1031 assert(isHandleInSync() && "invalid iterator access!");
10201032 return *Ptr;
10211033 }
10221034 pointer operator->() const {
1035 assert(isHandleInSync() && "invalid iterator access!");
10231036 return Ptr;
10241037 }
10251038
10261039 bool operator==(const ConstIterator &RHS) const {
1027 return Ptr == RHS.operator->();
1040 assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1041 assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1042 assert(getEpochAddress() == RHS.getEpochAddress() &&
1043 "comparing incomparable iterators!");
1044 return Ptr == RHS.Ptr;
10281045 }
10291046 bool operator!=(const ConstIterator &RHS) const {
1030 return Ptr != RHS.operator->();
1047 assert((!Ptr || isHandleInSync()) && "handle not in sync!");
1048 assert((!RHS.Ptr || RHS.isHandleInSync()) && "handle not in sync!");
1049 assert(getEpochAddress() == RHS.getEpochAddress() &&
1050 "comparing incomparable iterators!");
1051 return Ptr != RHS.Ptr;
10311052 }
10321053
10331054 inline DenseMapIterator& operator++() { // Preincrement
1055 assert(isHandleInSync() && "invalid iterator access!");
10341056 ++Ptr;
10351057 AdvancePastEmptyBuckets();
10361058 return *this;
10371059 }
10381060 DenseMapIterator operator++(int) { // Postincrement
1061 assert(isHandleInSync() && "invalid iterator access!");
10391062 DenseMapIterator tmp = *this; ++*this; return tmp;
10401063 }
10411064
0 //===- llvm/ADT/EpochTracker.h - ADT epoch tracking --------------*- C++ -*-==//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the DebugEpochBase and DebugEpochBase::HandleBase classes.
10 // These can be used to write iterators that are fail-fast when LLVM is built
11 // with asserts enabled.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_ADT_EPOCH_TRACKER_H
16 #define LLVM_ADT_EPOCH_TRACKER_H
17
18 #include "llvm/Config/llvm-config.h"
19
20 #include
21
22 namespace llvm {
23
24 #ifndef LLVM_ENABLE_ABI_BREAKING_CHECKS
25
26 class DebugEpochBase {
27 public:
28 void incrementEpoch() {}
29
30 class HandleBase {
31 public:
32 HandleBase() {}
33 explicit HandleBase(const DebugEpochBase *) {}
34 bool isHandleInSync() const { return true; }
35 const void *getEpochAddress() const { return nullptr; }
36 };
37 };
38
39 #else
40
41 /// \brief A base class for data structure classes wishing to make iterators
42 /// ("handles") pointing into themselves fail-fast. When building without
43 /// asserts, this class is empty and does nothing.
44 ///
45 /// DebugEpochBase does not by itself track handles pointing into itself. The
46 /// expectation is that routines touching the handles will poll on
47 /// isHandleInSync at appropriate points to assert that the handle they're using
48 /// is still valid.
49 ///
50 class DebugEpochBase {
51 uint64_t Epoch;
52
53 public:
54 DebugEpochBase() : Epoch(0) {}
55
56 /// \brief Calling incrementEpoch invalidates all handles pointing into the
57 /// calling instance.
58 void incrementEpoch() { ++Epoch; }
59
60 /// \brief The destructor calls incrementEpoch to make use-after-free bugs
61 /// more likely to crash deterministically.
62 ~DebugEpochBase() { incrementEpoch(); }
63
64 /// \brief A base class for iterator classes ("handles") that wish to poll for
65 /// iterator invalidating modifications in the underlying data structure.
66 /// When LLVM is built without asserts, this class is empty and does nothing.
67 ///
68 /// HandleBase does not track the parent data structure by itself. It expects
69 /// the routines modifying the data structure to call incrementEpoch when they
70 /// make an iterator-invalidating modification.
71 ///
72 class HandleBase {
73 const uint64_t *EpochAddress;
74 uint64_t EpochAtCreation;
75
76 public:
77 HandleBase() : EpochAddress(nullptr), EpochAtCreation(UINT64_MAX) {}
78
79 explicit HandleBase(const DebugEpochBase *Parent)
80 : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {}
81
82 /// \brief Returns true if the DebugEpochBase this Handle is linked to has
83 /// not called incrementEpoch on itself since the creation of this
84 /// HandleBase instance.
85 bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; }
86
87 /// \brief Returns a pointer to the epoch word stored in the data structure
88 /// this handle points into. Can be used to check if two iterators point
89 /// into the same data structure.
90 const void *getEpochAddress() const { return EpochAddress; }
91 };
92 };
93
94 #endif // LLVM_ENABLE_ABI_BREAKING_CHECKS
95
96 } // namespace llvm
97
98 #endif
416416 /* Installation directory for documentation */
417417 #undef LLVM_DOCSDIR
418418
419 /* Define to enable checks that alter the LLVM C++ ABI */
420 #undef LLVM_ENABLE_ABI_BREAKING_CHECKS
421
419422 /* Define if threads enabled */
420423 #undef LLVM_ENABLE_THREADS
421424
100100 /* Define if we link Polly to the tools */
101101 #cmakedefine LINK_POLLY_INTO_TOOLS
102102
103 /* Define if LLVM is built with asserts and checks that change the layout of
104 client-visible data structures. */
105 #cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS
106
103107 #endif
9797 /* LLVM version string */
9898 #undef LLVM_VERSION_STRING
9999
100 /* Define to enable checks that alter the LLVM C++ ABI */
101 #undef LLVM_ENABLE_ABI_BREAKING_CHECKS
102
100103 #endif