clang 23.0.0git
Utils.h
Go to the documentation of this file.
1//===- Utils.h - Utility Functions for Lifetime Safety --------*- C++ -*-===//
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// This file provides utilities for the lifetime safety analysis, including
8// join operations for LLVM's immutable data structures.
9//
10//===----------------------------------------------------------------------===//
11#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_UTILS_H
12#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_UTILS_H
13
14#include "llvm/ADT/ImmutableMap.h"
15#include "llvm/ADT/ImmutableSet.h"
16
18
19/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
20/// Used for giving ID to loans and origins.
21template <typename Tag> struct ID {
23
24 bool operator==(const ID<Tag> &Other) const { return Value == Other.Value; }
25 bool operator!=(const ID<Tag> &Other) const { return !(*this == Other); }
26 bool operator<(const ID<Tag> &Other) const { return Value < Other.Value; }
28 ID<Tag> Tmp = *this;
29 ++Value;
30 return Tmp;
31 }
32 void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
33 IDBuilder.AddInteger(Value);
34 }
35};
36
37/// Computes the union of two ImmutableSets.
38template <typename T>
39llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A, llvm::ImmutableSet<T> B,
40 typename llvm::ImmutableSet<T>::Factory &F) {
41 if (A.getHeight() < B.getHeight())
42 std::swap(A, B);
43 for (const T &E : B)
44 A = F.add(A, E);
45 return A;
46}
47
48/// Describes the strategy for joining two `ImmutableMap` instances, primarily
49/// differing in how they handle keys that are unique to one of the maps.
50///
51/// A `Symmetric` join is universally correct, while an `Asymmetric` join
52/// serves as a performance optimization. The latter is applicable only when the
53/// join operation possesses a left identity element, allowing for a more
54/// efficient, one-sided merge.
55enum class JoinKind {
56 /// A symmetric join applies the `JoinValues` operation to keys unique to
57 /// either map, ensuring that values from both maps contribute to the result.
59 /// An asymmetric join preserves keys unique to the first map as-is, while
60 /// applying the `JoinValues` operation only to keys unique to the second map.
62};
63
64/// Computes the key-wise union of two ImmutableMaps.
65// TODO(opt): This key-wise join is a performance bottleneck. A more
66// efficient merge could be implemented using a Patricia Trie or HAMT
67// instead of the current AVL-tree-based ImmutableMap.
68template <typename K, typename V, typename Joiner>
69llvm::ImmutableMap<K, V> join(const llvm::ImmutableMap<K, V> &A,
70 const llvm::ImmutableMap<K, V> &B,
71 typename llvm::ImmutableMap<K, V>::Factory &F,
72 Joiner JoinValues, JoinKind Kind) {
73 if (A.getHeight() < B.getHeight())
74 return join(B, A, F, JoinValues, Kind);
75
76 // For each element in B, join it with the corresponding element in A
77 // (or with an empty value if it doesn't exist in A).
78 llvm::ImmutableMap<K, V> Res = A;
79 for (const auto &Entry : B) {
80 const K &Key = Entry.first;
81 const V &ValB = Entry.second;
82 Res = F.add(Res, Key, JoinValues(A.lookup(Key), &ValB));
83 }
84 if (Kind == JoinKind::Symmetric) {
85 for (const auto &Entry : A) {
86 const K &Key = Entry.first;
87 const V &ValA = Entry.second;
88 if (!B.contains(Key))
89 Res = F.add(Res, Key, JoinValues(&ValA, nullptr));
90 }
91 }
92 return Res;
93}
94} // namespace clang::lifetimes::internal::utils
95
96namespace llvm {
97template <typename Tag>
98struct DenseMapInfo<clang::lifetimes::internal::utils::ID<Tag>> {
100
101 static unsigned getHashValue(const ID &Val) {
102 return DenseMapInfo<uint32_t>::getHashValue(Val.Value);
103 }
104
105 static bool isEqual(const ID &LHS, const ID &RHS) { return LHS == RHS; }
106};
107} // namespace llvm
108
109#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_UTILS_H
#define V(N, I)
JoinKind
Describes the strategy for joining two ImmutableMap instances, primarily differing in how they handle...
Definition Utils.h:55
@ Asymmetric
An asymmetric join preserves keys unique to the first map as-is, while applying the JoinValues operat...
Definition Utils.h:61
@ Symmetric
A symmetric join applies the JoinValues operation to keys unique to either map, ensuring that values ...
Definition Utils.h:58
llvm::ImmutableSet< T > join(llvm::ImmutableSet< T > A, llvm::ImmutableSet< T > B, typename llvm::ImmutableSet< T >::Factory &F)
Computes the union of two ImmutableSets.
Definition Utils.h:39
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
Definition Decl.h:1763
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
A generic, type-safe wrapper for an ID, distinguished by its Tag type.
Definition Utils.h:21
bool operator!=(const ID< Tag > &Other) const
Definition Utils.h:25
void Profile(llvm::FoldingSetNodeID &IDBuilder) const
Definition Utils.h:32
bool operator<(const ID< Tag > &Other) const
Definition Utils.h:26
bool operator==(const ID< Tag > &Other) const
Definition Utils.h:24
static bool isEqual(const ID &LHS, const ID &RHS)
Definition Utils.h:105
clang::lifetimes::internal::utils::ID< Tag > ID
Definition Utils.h:99