Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / tools / dsymutil / BinaryHolder.h
blobc4fc5a6110e775e6698158b82506652816ebe4d6
1 //===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
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 program is a utility that aims to be a dropin replacement for
10 // Darwin's dsymutil.
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
14 #define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/Object/Archive.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/MachOUniversal.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Chrono.h"
23 #include "llvm/Support/Errc.h"
24 #include "llvm/Support/ErrorOr.h"
25 #include "llvm/Support/VirtualFileSystem.h"
26 #include "llvm/TargetParser/Triple.h"
28 #include <mutex>
30 namespace llvm {
31 namespace dsymutil {
33 /// The BinaryHolder class is responsible for creating and owning
34 /// ObjectFiles and their underlying MemoryBuffers. It differs from a simple
35 /// OwningBinary in that it handles accessing and caching of archives and its
36 /// members.
37 class BinaryHolder {
38 public:
39 using TimestampTy = sys::TimePoint<std::chrono::seconds>;
41 BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool Verbose = false)
42 : VFS(VFS), Verbose(Verbose) {}
44 // Forward declarations for friend declaration.
45 class ObjectEntry;
46 class ArchiveEntry;
48 /// Base class shared by cached entries, representing objects and archives.
49 class EntryBase {
50 protected:
51 std::unique_ptr<MemoryBuffer> MemBuffer;
52 std::unique_ptr<object::MachOUniversalBinary> FatBinary;
53 std::string FatBinaryName;
56 /// Cached entry holding one or more (in case of a fat binary) object files.
57 class ObjectEntry : public EntryBase {
58 public:
59 /// Load the given object binary in memory.
60 Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
61 TimestampTy Timestamp, bool Verbose = false);
63 /// Access all owned ObjectFiles.
64 std::vector<const object::ObjectFile *> getObjects() const;
66 /// Access to a derived version of all the currently owned ObjectFiles. The
67 /// conversion might be invalid, in which case an Error is returned.
68 template <typename ObjectFileType>
69 Expected<std::vector<const ObjectFileType *>> getObjectsAs() const {
70 std::vector<const ObjectFileType *> Result;
71 Result.reserve(Objects.size());
72 for (auto &Object : Objects) {
73 const auto *Derived = dyn_cast<ObjectFileType>(Object.get());
74 if (!Derived)
75 return errorCodeToError(object::object_error::invalid_file_type);
76 Result.push_back(Derived);
78 return Result;
81 /// Access the owned ObjectFile with architecture \p T.
82 Expected<const object::ObjectFile &> getObject(const Triple &T) const;
84 /// Access to a derived version of the currently owned ObjectFile with
85 /// architecture \p T. The conversion must be known to be valid.
86 template <typename ObjectFileType>
87 Expected<const ObjectFileType &> getObjectAs(const Triple &T) const {
88 auto Object = getObject(T);
89 if (!Object)
90 return Object.takeError();
91 return cast<ObjectFileType>(*Object);
94 private:
95 std::vector<std::unique_ptr<object::ObjectFile>> Objects;
96 friend ArchiveEntry;
99 /// Cached entry holding one or more (in the of a fat binary) archive files.
100 class ArchiveEntry : public EntryBase {
101 public:
102 struct KeyTy {
103 std::string Filename;
104 TimestampTy Timestamp;
106 KeyTy() {}
107 KeyTy(StringRef Filename, TimestampTy Timestamp)
108 : Filename(Filename.str()), Timestamp(Timestamp) {}
111 /// Load the given object binary in memory.
112 Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
113 TimestampTy Timestamp, bool Verbose = false);
115 Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,
116 TimestampTy Timestamp,
117 bool Verbose = false);
119 private:
120 std::vector<std::unique_ptr<object::Archive>> Archives;
121 DenseMap<KeyTy, std::unique_ptr<ObjectEntry>> MemberCache;
122 std::mutex MemberCacheMutex;
125 Expected<const ObjectEntry &>
126 getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());
128 void clear();
129 void eraseObjectEntry(StringRef Filename);
131 private:
132 /// Cache of static archives. Objects that are part of a static archive are
133 /// stored under this object, rather than in the map below.
134 StringMap<std::unique_ptr<ArchiveEntry>> ArchiveCache;
135 StringMap<uint32_t> ArchiveRefCounter;
136 std::mutex ArchiveCacheMutex;
138 /// Object entries for objects that are not in a static archive.
139 StringMap<std::unique_ptr<ObjectEntry>> ObjectCache;
140 StringMap<uint32_t> ObjectRefCounter;
141 std::mutex ObjectCacheMutex;
143 /// Virtual File System instance.
144 IntrusiveRefCntPtr<vfs::FileSystem> VFS;
146 bool Verbose;
149 } // namespace dsymutil
151 template <> struct DenseMapInfo<dsymutil::BinaryHolder::ArchiveEntry::KeyTy> {
153 static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getEmptyKey() {
154 return dsymutil::BinaryHolder::ArchiveEntry::KeyTy();
157 static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getTombstoneKey() {
158 return dsymutil::BinaryHolder::ArchiveEntry::KeyTy("/", {});
161 static unsigned
162 getHashValue(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &K) {
163 return hash_combine(DenseMapInfo<StringRef>::getHashValue(K.Filename),
164 DenseMapInfo<unsigned>::getHashValue(
165 K.Timestamp.time_since_epoch().count()));
168 static bool isEqual(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &LHS,
169 const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &RHS) {
170 return LHS.Filename == RHS.Filename && LHS.Timestamp == RHS.Timestamp;
174 } // namespace llvm
175 #endif