clang 22.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 {
22 uint32_t Value = 0;
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>
39static llvm::ImmutableSet<T> join(llvm::ImmutableSet<T> A,
40 llvm::ImmutableSet<T> B,
41 typename llvm::ImmutableSet<T>::Factory &F) {
42 if (A.getHeight() < B.getHeight())
43 std::swap(A, B);
44 for (const T &E : B)
45 A = F.add(A, E);
46 return A;
47}
48
49/// Describes the strategy for joining two `ImmutableMap` instances, primarily
50/// differing in how they handle keys that are unique to one of the maps.
51///
52/// A `Symmetric` join is universally correct, while an `Asymmetric` join
53/// serves as a performance optimization. The latter is applicable only when the
54/// join operation possesses a left identity element, allowing for a more
55/// efficient, one-sided merge.
56enum class JoinKind {
57 /// A symmetric join applies the `JoinValues` operation to keys unique to
58 /// either map, ensuring that values from both maps contribute to the result.
60 /// An asymmetric join preserves keys unique to the first map as-is, while
61 /// applying the `JoinValues` operation only to keys unique to the second map.
63};
64
65/// Computes the key-wise union of two ImmutableMaps.
66// TODO(opt): This key-wise join is a performance bottleneck. A more
67// efficient merge could be implemented using a Patricia Trie or HAMT
68// instead of the current AVL-tree-based ImmutableMap.
69template <typename K, typename V, typename Joiner>
70static llvm::ImmutableMap<K, V>
71join(const llvm::ImmutableMap<K, V> &A, const llvm::ImmutableMap<K, V> &B,
72 typename llvm::ImmutableMap<K, V>::Factory &F, Joiner JoinValues,
73 JoinKind Kind) {
74 if (A.getHeight() < B.getHeight())
75 return join(B, A, F, JoinValues, Kind);
76
77 // For each element in B, join it with the corresponding element in A
78 // (or with an empty value if it doesn't exist in A).
79 llvm::ImmutableMap<K, V> Res = A;
80 for (const auto &Entry : B) {
81 const K &Key = Entry.first;
82 const V &ValB = Entry.second;
83 Res = F.add(Res, Key, JoinValues(A.lookup(Key), &ValB));
84 }
85 if (Kind == JoinKind::Symmetric) {
86 for (const auto &Entry : A) {
87 const K &Key = Entry.first;
88 const V &ValA = Entry.second;
89 if (!B.contains(Key))
90 Res = F.add(Res, Key, JoinValues(&ValA, nullptr));
91 }
92 }
93 return Res;
94}
95} // namespace clang::lifetimes::internal::utils
96
97namespace llvm {
98template <typename Tag>
99struct DenseMapInfo<clang::lifetimes::internal::utils::ID<Tag>> {
101
102 static inline ID getEmptyKey() {
103 return {DenseMapInfo<uint32_t>::getEmptyKey()};
104 }
105
106 static inline ID getTombstoneKey() {
107 return {DenseMapInfo<uint32_t>::getTombstoneKey()};
108 }
109
110 static unsigned getHashValue(const ID &Val) {
111 return DenseMapInfo<uint32_t>::getHashValue(Val.Value);
112 }
113
114 static bool isEqual(const ID &LHS, const ID &RHS) { return LHS == RHS; }
115};
116} // namespace llvm
117
118#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:56
@ Asymmetric
An asymmetric join preserves keys unique to the first map as-is, while applying the JoinValues operat...
Definition Utils.h:62
@ Symmetric
A symmetric join applies the JoinValues operation to keys unique to either map, ensuring that values ...
Definition Utils.h:59
static 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.
const FunctionProtoType * T
@ Other
Other implicit parameter.
Definition Decl.h:1746
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
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:114
clang::lifetimes::internal::utils::ID< Tag > ID
Definition Utils.h:100