Skip to content

Commit 9abb3f0

Browse files
authored
Merge pull request #9172 from github/redsun82/swift-variant-in-label-store
Swift: replace `getCanonicalPointer` with `std::variant`
2 parents 23981cb + 16e3b5b commit 9abb3f0

File tree

5 files changed

+37
-43
lines changed

5 files changed

+37
-43
lines changed

swift/extractor/SwiftDispatcher.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ std::string inline getKindName<swift::TypeRepr, swift::TypeReprKind>(swift::Type
4646

4747
} // namespace detail
4848

49-
// The main reponsibilities of the SwiftDispatcher are as follows:
49+
// The main responsibilities of the SwiftDispatcher are as follows:
5050
// * redirect specific AST node emission to a corresponding visitor (statements, expressions, etc.)
5151
// * storing TRAP labels for emitted AST nodes (in the TrapLabelStore) to avoid re-emission
5252
// Since SwiftDispatcher sees all the AST nodes, it also attaches a location to every 'locatable'
@@ -72,19 +72,28 @@ class SwiftDispatcher {
7272
}
7373

7474
private:
75+
// types to be supported by assignNewLabel/fetchLabel need to be listed here
76+
using Store = TrapLabelStore<swift::Decl,
77+
swift::Stmt,
78+
swift::Expr,
79+
swift::Pattern,
80+
swift::TypeRepr,
81+
swift::TypeBase>;
82+
7583
// This method gives a TRAP label for already emitted AST node.
7684
// If the AST node was not emitted yet, then the emission is dispatched to a corresponding
7785
// visitor (see `visit(T *)` methods below).
7886
template <typename E>
79-
TrapLabel<ToTag<E>> fetchLabel(E* e) {
87+
TrapLabelOf<E> fetchLabel(E* e) {
8088
// this is required so we avoid any recursive loop: a `fetchLabel` during the visit of `e` might
8189
// end up calling `fetchLabel` on `e` itself, so we want the visit of `e` to call `fetchLabel`
82-
// only after having called `assignNewLabel` on `e`
83-
assert(!waitingForNewLabel && "fetchLabel called before assignNewLabel");
90+
// only after having called `assignNewLabel` on `e`.
91+
assert(holds_alternative<std::monostate>(waitingForNewLabel) &&
92+
"fetchLabel called before assignNewLabel");
8493
if (auto l = store.get(e)) {
8594
return *l;
8695
}
87-
waitingForNewLabel = getCanonicalPointer(e);
96+
waitingForNewLabel = e;
8897
visit(e);
8998
if (auto l = store.get(e)) {
9099
if constexpr (!std::is_base_of_v<swift::TypeBase, E>) {
@@ -100,12 +109,12 @@ class SwiftDispatcher {
100109
// it actually gets emitted to handle recursive cases such as recursive calls, or recursive type
101110
// declarations
102111
template <typename E>
103-
TrapLabel<ToTag<E>> assignNewLabel(E* e) {
104-
assert(waitingForNewLabel == getCanonicalPointer(e) && "assignNewLabel called on wrong entity");
105-
auto label = getLabel<ToTag<E>>();
112+
TrapLabelOf<E> assignNewLabel(E* e) {
113+
assert(waitingForNewLabel == Store::Handle{e} && "assignNewLabel called on wrong entity");
114+
auto label = getLabel<TrapTagOf<E>>();
106115
trap.assignStar(label);
107116
store.insert(e, label);
108-
waitingForNewLabel = nullptr;
117+
waitingForNewLabel = std::monostate{};
109118
return label;
110119
}
111120

@@ -167,8 +176,8 @@ class SwiftDispatcher {
167176
const swift::SourceManager& sourceManager;
168177
TrapArena& arena;
169178
TrapOutput& trap;
170-
TrapLabelStore store;
171-
const void* waitingForNewLabel{nullptr};
179+
Store store;
180+
Store::Handle waitingForNewLabel{std::monostate{}};
172181
};
173182

174183
} // namespace codeql

swift/extractor/SwiftTagTraits.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

3-
// This file implements the mapping needed by the API defined in the TrapTagTraits.h
3+
// This file implements the mapping needed by the API defined in the TrapTagTraits.h, so that
4+
// TrapTagOf/TrapLabelOf provide the tags/labels for specific swift entity types.
45
#include <swift/AST/ASTVisitor.h>
56
#include "swift/extractor/trap/TrapTagTraits.h"
67
#include "swift/extractor/trap/generated/TrapTags.h"

swift/extractor/trap/TrapLabel.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <iostream>
55
#include <string>
66

7-
#include "swift/extractor/trap/TrapTagTraits.h"
87
#include "swift/extractor/trap/generated/TrapTags.h"
98

109
namespace codeql {

swift/extractor/trap/TrapLabelStore.h

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <variant>
34
#include <cassert>
45
#include <optional>
56
#include <unordered_map>
@@ -12,50 +13,31 @@
1213

1314
namespace codeql {
1415

15-
// The following is needed to avoid the problem of subclass pointers not necessarily coinciding
16-
// with superclass ones in case of multiple inheritance
17-
// The interesting part here is implicit conversion from a derived class pointer to the parameter
18-
inline const swift::Decl* getCanonicalPointer(const swift::Decl* e) {
19-
return e;
20-
}
21-
inline const swift::Stmt* getCanonicalPointer(const swift::Stmt* e) {
22-
return e;
23-
}
24-
inline const swift::Expr* getCanonicalPointer(const swift::Expr* e) {
25-
return e;
26-
}
27-
inline const swift::Pattern* getCanonicalPointer(const swift::Pattern* e) {
28-
return e;
29-
}
30-
inline const swift::TypeRepr* getCanonicalPointer(const swift::TypeRepr* e) {
31-
return e;
32-
}
33-
inline const swift::TypeBase* getCanonicalPointer(const swift::TypeBase* e) {
34-
return e;
35-
}
36-
3716
// The extraction is done in a lazy/on-demand fashion:
3817
// Each emitted TRAP entry for an AST node gets a TRAP label assigned to it.
3918
// To avoid re-emission, we store the "AST node <> label" entry in the TrapLabelStore.
19+
// The template parameters `Ts...` indicate to what entity types we restrict the storage
20+
template <typename... Ts>
4021
class TrapLabelStore {
4122
public:
23+
using Handle = std::variant<std::monostate, const Ts*...>;
24+
4225
template <typename T>
43-
std::optional<TrapLabel<ToTag<T>>> get(const T* e) {
44-
if (auto found = store_.find(getCanonicalPointer(e)); found != store_.end()) {
45-
return TrapLabel<ToTag<T>>::unsafeCreateFromUntyped(found->second);
26+
std::optional<TrapLabelOf<T>> get(const T* e) {
27+
if (auto found = store_.find(e); found != store_.end()) {
28+
return TrapLabelOf<T>::unsafeCreateFromUntyped(found->second);
4629
}
4730
return std::nullopt;
4831
}
4932

5033
template <typename T>
51-
void insert(const T* e, TrapLabel<ToTag<T>> l) {
52-
auto [_, inserted] = store_.emplace(getCanonicalPointer(e), l);
34+
void insert(const T* e, TrapLabelOf<T> l) {
35+
auto [_, inserted] = store_.emplace(e, l);
5336
assert(inserted && "already inserted");
5437
}
5538

5639
private:
57-
// TODO: consider std::variant or llvm::PointerUnion instead of `void *`
58-
std::unordered_map<const void*, UntypedTrapLabel> store_;
40+
std::unordered_map<Handle, UntypedTrapLabel> store_;
5941
};
6042

6143
} // namespace codeql

swift/extractor/trap/TrapTagTraits.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ struct ToTagOverride : ToTagFunctor<T> {};
1616
} // namespace detail
1717

1818
template <typename T>
19-
using ToTag = typename detail::ToTagOverride<std::remove_const_t<T>>::type;
19+
using TrapTagOf = typename detail::ToTagOverride<std::remove_const_t<T>>::type;
20+
21+
template <typename T>
22+
using TrapLabelOf = TrapLabel<TrapTagOf<T>>;
2023

2124
} // namespace codeql

0 commit comments

Comments
 (0)