|
| 1 | +//===----- ModuleSummary.h --------------------------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | +// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | + |
| 13 | +#ifndef SWIFT_SIL_MODULE_SUMMARY_H |
| 14 | +#define SWIFT_SIL_MODULE_SUMMARY_H |
| 15 | + |
| 16 | +#include "swift/AST/Decl.h" |
| 17 | +#include "swift/SIL/SILFunction.h" |
| 18 | +#include "llvm/Support/YAMLTraits.h" |
| 19 | + |
| 20 | +namespace swift { |
| 21 | + |
| 22 | +namespace modulesummary { |
| 23 | + |
| 24 | +using GUID = uint64_t; |
| 25 | + |
| 26 | +/// Compute globally unique identifier from the symbol. |
| 27 | +GUID getGUIDFromUniqueName(llvm::StringRef Name); |
| 28 | + |
| 29 | +/// Function summary information to help callee analysis |
| 30 | +class FunctionSummary { |
| 31 | +public: |
| 32 | + /// Function call information |
| 33 | + class Call { |
| 34 | + public: |
| 35 | + /// Kinds of callee reference. |
| 36 | + enum KindTy { |
| 37 | + /// The call references a function statically |
| 38 | + Direct, |
| 39 | + /// The call references a function via a witness table. |
| 40 | + Witness, |
| 41 | + /// The call references a function via a vtable. |
| 42 | + VTable, |
| 43 | + kindCount, |
| 44 | + }; |
| 45 | + |
| 46 | + private: |
| 47 | + // For import/export |
| 48 | + friend llvm::yaml::MappingTraits<FunctionSummary::Call>; |
| 49 | + |
| 50 | + /// The callee function GUID. This can be a static function or a virtual |
| 51 | + /// function GUID. |
| 52 | + GUID Callee; |
| 53 | + /// The symbol name of the callee function only for debug and test purposes. |
| 54 | + std::string Name; |
| 55 | + /// Kind of the callee reference. |
| 56 | + KindTy Kind; |
| 57 | + public: |
| 58 | + friend ::llvm::yaml::MappingTraits<Call>; |
| 59 | + Call() = default; |
| 60 | + Call(GUID callee, std::string name, KindTy kind) |
| 61 | + : Callee(callee), Name(name), Kind(kind) {} |
| 62 | + |
| 63 | + KindTy getKind() const { return Kind; } |
| 64 | + GUID getCallee() const { return Callee; } |
| 65 | + std::string getName() const { return Name; }; |
| 66 | + }; |
| 67 | + |
| 68 | + /// Function state flags |
| 69 | + struct FlagsTy { |
| 70 | + /// In per-module summary, always false. |
| 71 | + /// In combined summary, indicates that the function is live. |
| 72 | + bool Live; |
| 73 | + /// Indicates that the function must be considered a live root for liveness |
| 74 | + /// analysis. |
| 75 | + bool Preserved; |
| 76 | + }; |
| 77 | + |
| 78 | + using CallGraphEdgeListTy = std::vector<Call>; |
| 79 | + |
| 80 | +private: |
| 81 | + // For import/export |
| 82 | + friend llvm::yaml::MappingTraits<FunctionSummary>; |
| 83 | + |
| 84 | + /// The function identity. |
| 85 | + GUID Guid; |
| 86 | + /// The function state flags. |
| 87 | + FlagsTy Flags; |
| 88 | + /// List of Call from this function. |
| 89 | + CallGraphEdgeListTy CallGraphEdgeList; |
| 90 | + /// The symbol name of the function only for debug and test purposes. |
| 91 | + std::string Name; |
| 92 | + |
| 93 | +public: |
| 94 | + FunctionSummary() = default; |
| 95 | + FunctionSummary(GUID guid) |
| 96 | + : Guid(guid), Flags({false, false}), CallGraphEdgeList(), Name("") {} |
| 97 | + |
| 98 | + /// Add a call to the list. |
| 99 | + void addCall(Call call) { CallGraphEdgeList.push_back(call); } |
| 100 | + |
| 101 | + /// Return the list of Call from this function |
| 102 | + ArrayRef<Call> calls() const { return CallGraphEdgeList; } |
| 103 | + |
| 104 | + bool isLive() const { return Flags.Live; } |
| 105 | + void setLive(bool Live) { Flags.Live = Live; } |
| 106 | + |
| 107 | + bool isPreserved() const { return Flags.Preserved; } |
| 108 | + void setPreserved(bool Preserved) { Flags.Preserved = Preserved; } |
| 109 | + |
| 110 | + std::string getName() const { return Name; } |
| 111 | + void setName(std::string name) { this->Name = name; } |
| 112 | + |
| 113 | + GUID getGUID() const { return Guid; } |
| 114 | +}; |
| 115 | + |
| 116 | +/// A slot in a set of virtual tables. |
| 117 | +struct VFuncSlot { |
| 118 | + /// Kinds of table. |
| 119 | + enum KindTy { |
| 120 | + Witness, |
| 121 | + VTable, |
| 122 | + kindCount, |
| 123 | + }; |
| 124 | + |
| 125 | + /// Kind of table. |
| 126 | + KindTy Kind; |
| 127 | + /// The virtual function GUID. |
| 128 | + GUID VFuncID; |
| 129 | + |
| 130 | + VFuncSlot(KindTy Kind, GUID VFuncID) : Kind(Kind), VFuncID(VFuncID) {} |
| 131 | +}; |
| 132 | + |
| 133 | +struct VFuncImpl { |
| 134 | + GUID Guid; |
| 135 | + GUID TypeGuid; |
| 136 | +}; |
| 137 | + |
| 138 | +using FunctionSummaryMapTy = std::map<GUID, std::unique_ptr<FunctionSummary>>; |
| 139 | +using VFuncToImplsMapTy = std::map<GUID, std::vector<VFuncImpl>>; |
| 140 | + |
| 141 | +/// Module summary that consists of function summaries and virtual function |
| 142 | +/// tables. |
| 143 | +class ModuleSummaryIndex { |
| 144 | + // For import/export |
| 145 | + friend llvm::yaml::MappingTraits<ModuleSummaryIndex>; |
| 146 | + |
| 147 | + /// Map from function GUID to function summary. |
| 148 | + FunctionSummaryMapTy FunctionSummaryMap; |
| 149 | + /// Map from virtual function GUID to list of implementations for witness |
| 150 | + /// tables. |
| 151 | + VFuncToImplsMapTy WitnessTableMethodMap; |
| 152 | + /// Map from virtual function GUID to list of implementations for vtables. |
| 153 | + VFuncToImplsMapTy VTableMethodMap; |
| 154 | + /// The symbol name of the module. |
| 155 | + std::string Name; |
| 156 | + |
| 157 | + VFuncToImplsMapTy &getVFuncMap(VFuncSlot::KindTy kind) { |
| 158 | + switch (kind) { |
| 159 | + case VFuncSlot::Witness: |
| 160 | + return WitnessTableMethodMap; |
| 161 | + case VFuncSlot::VTable: |
| 162 | + return VTableMethodMap; |
| 163 | + case VFuncSlot::kindCount: { |
| 164 | + llvm_unreachable("impossible"); |
| 165 | + } |
| 166 | + } |
| 167 | + } |
| 168 | + const VFuncToImplsMapTy &getVFuncMap(VFuncSlot::KindTy kind) const { |
| 169 | + switch (kind) { |
| 170 | + case VFuncSlot::Witness: |
| 171 | + return WitnessTableMethodMap; |
| 172 | + case VFuncSlot::VTable: |
| 173 | + return VTableMethodMap; |
| 174 | + case VFuncSlot::kindCount: { |
| 175 | + llvm_unreachable("impossible"); |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | +public: |
| 180 | + friend ::llvm::yaml::MappingTraits<ModuleSummaryIndex>; |
| 181 | + ModuleSummaryIndex() = default; |
| 182 | + |
| 183 | + std::string getName() const { return this->Name; } |
| 184 | + void setName(std::string name) { this->Name = name; } |
| 185 | + |
| 186 | + /// Add a global value summary. |
| 187 | + void addFunctionSummary(std::unique_ptr<FunctionSummary> summary) { |
| 188 | + FunctionSummaryMap.insert( |
| 189 | + std::make_pair(summary->getGUID(), std::move(summary))); |
| 190 | + } |
| 191 | + |
| 192 | + /// Return a FunctionSummary for GUID if it exists, otherwise return nullptr. |
| 193 | + FunctionSummary *getFunctionSummary(GUID guid) const { |
| 194 | + auto found = FunctionSummaryMap.find(guid); |
| 195 | + if (found == FunctionSummaryMap.end()) { |
| 196 | + return nullptr; |
| 197 | + } |
| 198 | + auto &entry = found->second; |
| 199 | + return entry.get(); |
| 200 | + } |
| 201 | + |
| 202 | + /// Record a implementation for the virtual function slot. |
| 203 | + void addImplementation(VFuncSlot slot, GUID implGUID, GUID typeGUID) { |
| 204 | + VFuncToImplsMapTy &table = getVFuncMap(slot.Kind); |
| 205 | + auto found = table.find(slot.VFuncID); |
| 206 | + VFuncImpl impl = {implGUID, typeGUID}; |
| 207 | + if (found == table.end()) { |
| 208 | + table.insert(std::make_pair(slot.VFuncID, std::vector<VFuncImpl>{impl})); |
| 209 | + return; |
| 210 | + } |
| 211 | + found->second.push_back(impl); |
| 212 | + } |
| 213 | + |
| 214 | + /// Return a list of implementations for the virtual function slot. |
| 215 | + ArrayRef<VFuncImpl> getImplementations(VFuncSlot slot) const { |
| 216 | + const VFuncToImplsMapTy &table = getVFuncMap(slot.Kind); |
| 217 | + auto found = table.find(slot.VFuncID); |
| 218 | + if (found == table.end()) { |
| 219 | + return ArrayRef<VFuncImpl>(); |
| 220 | + } |
| 221 | + return ArrayRef<VFuncImpl>(found->second); |
| 222 | + } |
| 223 | + |
| 224 | + const VFuncToImplsMapTy &getWitnessTableMethodMap() const { |
| 225 | + return WitnessTableMethodMap; |
| 226 | + } |
| 227 | + const VFuncToImplsMapTy &getVTableMethodMap() const { |
| 228 | + return VTableMethodMap; |
| 229 | + } |
| 230 | + |
| 231 | + FunctionSummaryMapTy::const_iterator functions_begin() const { |
| 232 | + return FunctionSummaryMap.begin(); |
| 233 | + } |
| 234 | + FunctionSummaryMapTy::const_iterator functions_end() const { |
| 235 | + return FunctionSummaryMap.end(); |
| 236 | + } |
| 237 | +}; |
| 238 | + |
| 239 | +/// Compute a \c ModuleSummaryIndex from the given SILModule. |
| 240 | +std::unique_ptr<ModuleSummaryIndex> buildModuleSummaryIndex(SILModule &M); |
| 241 | + |
| 242 | +/// Serializes a module summary to the given output file. |
| 243 | +/// |
| 244 | +/// \returns false on success, true on error. |
| 245 | +bool writeModuleSummaryIndex(const ModuleSummaryIndex &index, |
| 246 | + DiagnosticEngine &diags, StringRef path); |
| 247 | + |
| 248 | +/// Attempt to deserialize the module summary. |
| 249 | +/// |
| 250 | +/// \returns false on success, true on error. |
| 251 | +bool loadModuleSummaryIndex(llvm::MemoryBufferRef inputBuffer, |
| 252 | + ModuleSummaryIndex &moduleSummary); |
| 253 | +} // namespace modulesummary |
| 254 | +} // namespace swift |
| 255 | + |
| 256 | +#endif |
0 commit comments