ModuleSummaryIndexYAML.h revision 360784
1//===-- llvm/ModuleSummaryIndexYAML.h - YAML I/O for summary ----*- 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//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_IR_MODULESUMMARYINDEXYAML_H
10#define LLVM_IR_MODULESUMMARYINDEXYAML_H
11
12#include "llvm/IR/ModuleSummaryIndex.h"
13#include "llvm/Support/YAMLTraits.h"
14
15namespace llvm {
16namespace yaml {
17
18template <> struct ScalarEnumerationTraits<TypeTestResolution::Kind> {
19  static void enumeration(IO &io, TypeTestResolution::Kind &value) {
20    io.enumCase(value, "Unsat", TypeTestResolution::Unsat);
21    io.enumCase(value, "ByteArray", TypeTestResolution::ByteArray);
22    io.enumCase(value, "Inline", TypeTestResolution::Inline);
23    io.enumCase(value, "Single", TypeTestResolution::Single);
24    io.enumCase(value, "AllOnes", TypeTestResolution::AllOnes);
25  }
26};
27
28template <> struct MappingTraits<TypeTestResolution> {
29  static void mapping(IO &io, TypeTestResolution &res) {
30    io.mapOptional("Kind", res.TheKind);
31    io.mapOptional("SizeM1BitWidth", res.SizeM1BitWidth);
32    io.mapOptional("AlignLog2", res.AlignLog2);
33    io.mapOptional("SizeM1", res.SizeM1);
34    io.mapOptional("BitMask", res.BitMask);
35    io.mapOptional("InlineBits", res.InlineBits);
36  }
37};
38
39template <>
40struct ScalarEnumerationTraits<WholeProgramDevirtResolution::ByArg::Kind> {
41  static void enumeration(IO &io,
42                          WholeProgramDevirtResolution::ByArg::Kind &value) {
43    io.enumCase(value, "Indir", WholeProgramDevirtResolution::ByArg::Indir);
44    io.enumCase(value, "UniformRetVal",
45                WholeProgramDevirtResolution::ByArg::UniformRetVal);
46    io.enumCase(value, "UniqueRetVal",
47                WholeProgramDevirtResolution::ByArg::UniqueRetVal);
48    io.enumCase(value, "VirtualConstProp",
49                WholeProgramDevirtResolution::ByArg::VirtualConstProp);
50  }
51};
52
53template <> struct MappingTraits<WholeProgramDevirtResolution::ByArg> {
54  static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) {
55    io.mapOptional("Kind", res.TheKind);
56    io.mapOptional("Info", res.Info);
57    io.mapOptional("Byte", res.Byte);
58    io.mapOptional("Bit", res.Bit);
59  }
60};
61
62template <>
63struct CustomMappingTraits<
64    std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg>> {
65  static void inputOne(
66      IO &io, StringRef Key,
67      std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
68    std::vector<uint64_t> Args;
69    std::pair<StringRef, StringRef> P = {"", Key};
70    while (!P.second.empty()) {
71      P = P.second.split(',');
72      uint64_t Arg;
73      if (P.first.getAsInteger(0, Arg)) {
74        io.setError("key not an integer");
75        return;
76      }
77      Args.push_back(Arg);
78    }
79    io.mapRequired(Key.str().c_str(), V[Args]);
80  }
81  static void output(
82      IO &io,
83      std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
84    for (auto &P : V) {
85      std::string Key;
86      for (uint64_t Arg : P.first) {
87        if (!Key.empty())
88          Key += ',';
89        Key += llvm::utostr(Arg);
90      }
91      io.mapRequired(Key.c_str(), P.second);
92    }
93  }
94};
95
96template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
97  static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) {
98    io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir);
99    io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
100    io.enumCase(value, "BranchFunnel",
101                WholeProgramDevirtResolution::BranchFunnel);
102  }
103};
104
105template <> struct MappingTraits<WholeProgramDevirtResolution> {
106  static void mapping(IO &io, WholeProgramDevirtResolution &res) {
107    io.mapOptional("Kind", res.TheKind);
108    io.mapOptional("SingleImplName", res.SingleImplName);
109    io.mapOptional("ResByArg", res.ResByArg);
110  }
111};
112
113template <>
114struct CustomMappingTraits<std::map<uint64_t, WholeProgramDevirtResolution>> {
115  static void inputOne(IO &io, StringRef Key,
116                       std::map<uint64_t, WholeProgramDevirtResolution> &V) {
117    uint64_t KeyInt;
118    if (Key.getAsInteger(0, KeyInt)) {
119      io.setError("key not an integer");
120      return;
121    }
122    io.mapRequired(Key.str().c_str(), V[KeyInt]);
123  }
124  static void output(IO &io, std::map<uint64_t, WholeProgramDevirtResolution> &V) {
125    for (auto &P : V)
126      io.mapRequired(llvm::utostr(P.first).c_str(), P.second);
127  }
128};
129
130template <> struct MappingTraits<TypeIdSummary> {
131  static void mapping(IO &io, TypeIdSummary& summary) {
132    io.mapOptional("TTRes", summary.TTRes);
133    io.mapOptional("WPDRes", summary.WPDRes);
134  }
135};
136
137struct FunctionSummaryYaml {
138  unsigned Linkage;
139  bool NotEligibleToImport, Live, IsLocal, CanAutoHide;
140  std::vector<uint64_t> Refs;
141  std::vector<uint64_t> TypeTests;
142  std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
143      TypeCheckedLoadVCalls;
144  std::vector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
145      TypeCheckedLoadConstVCalls;
146};
147
148} // End yaml namespace
149} // End llvm namespace
150
151namespace llvm {
152namespace yaml {
153
154template <> struct MappingTraits<FunctionSummary::VFuncId> {
155  static void mapping(IO &io, FunctionSummary::VFuncId& id) {
156    io.mapOptional("GUID", id.GUID);
157    io.mapOptional("Offset", id.Offset);
158  }
159};
160
161template <> struct MappingTraits<FunctionSummary::ConstVCall> {
162  static void mapping(IO &io, FunctionSummary::ConstVCall& id) {
163    io.mapOptional("VFunc", id.VFunc);
164    io.mapOptional("Args", id.Args);
165  }
166};
167
168} // End yaml namespace
169} // End llvm namespace
170
171LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId)
172LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall)
173
174namespace llvm {
175namespace yaml {
176
177template <> struct MappingTraits<FunctionSummaryYaml> {
178  static void mapping(IO &io, FunctionSummaryYaml& summary) {
179    io.mapOptional("Linkage", summary.Linkage);
180    io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport);
181    io.mapOptional("Live", summary.Live);
182    io.mapOptional("Local", summary.IsLocal);
183    io.mapOptional("CanAutoHide", summary.CanAutoHide);
184    io.mapOptional("Refs", summary.Refs);
185    io.mapOptional("TypeTests", summary.TypeTests);
186    io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
187    io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
188    io.mapOptional("TypeTestAssumeConstVCalls",
189                   summary.TypeTestAssumeConstVCalls);
190    io.mapOptional("TypeCheckedLoadConstVCalls",
191                   summary.TypeCheckedLoadConstVCalls);
192  }
193};
194
195} // End yaml namespace
196} // End llvm namespace
197
198LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml)
199
200namespace llvm {
201namespace yaml {
202
203// FIXME: Add YAML mappings for the rest of the module summary.
204template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
205  static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) {
206    std::vector<FunctionSummaryYaml> FSums;
207    io.mapRequired(Key.str().c_str(), FSums);
208    uint64_t KeyInt;
209    if (Key.getAsInteger(0, KeyInt)) {
210      io.setError("key not an integer");
211      return;
212    }
213    if (!V.count(KeyInt))
214      V.emplace(KeyInt, /*IsAnalysis=*/false);
215    auto &Elem = V.find(KeyInt)->second;
216    for (auto &FSum : FSums) {
217      std::vector<ValueInfo> Refs;
218      for (auto &RefGUID : FSum.Refs) {
219        if (!V.count(RefGUID))
220          V.emplace(RefGUID, /*IsAnalysis=*/false);
221        Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID)));
222      }
223      Elem.SummaryList.push_back(std::make_unique<FunctionSummary>(
224          GlobalValueSummary::GVFlags(
225              static_cast<GlobalValue::LinkageTypes>(FSum.Linkage),
226              FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal, FSum.CanAutoHide),
227          /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, Refs,
228          ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
229          std::move(FSum.TypeTestAssumeVCalls),
230          std::move(FSum.TypeCheckedLoadVCalls),
231          std::move(FSum.TypeTestAssumeConstVCalls),
232          std::move(FSum.TypeCheckedLoadConstVCalls)));
233    }
234  }
235  static void output(IO &io, GlobalValueSummaryMapTy &V) {
236    for (auto &P : V) {
237      std::vector<FunctionSummaryYaml> FSums;
238      for (auto &Sum : P.second.SummaryList) {
239        if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) {
240          std::vector<uint64_t> Refs;
241          for (auto &VI : FSum->refs())
242            Refs.push_back(VI.getGUID());
243          FSums.push_back(FunctionSummaryYaml{
244              FSum->flags().Linkage,
245              static_cast<bool>(FSum->flags().NotEligibleToImport),
246              static_cast<bool>(FSum->flags().Live),
247              static_cast<bool>(FSum->flags().DSOLocal),
248              static_cast<bool>(FSum->flags().CanAutoHide), Refs,
249              FSum->type_tests(), FSum->type_test_assume_vcalls(),
250              FSum->type_checked_load_vcalls(),
251              FSum->type_test_assume_const_vcalls(),
252              FSum->type_checked_load_const_vcalls()});
253          }
254      }
255      if (!FSums.empty())
256        io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
257    }
258  }
259};
260
261template <> struct CustomMappingTraits<TypeIdSummaryMapTy> {
262  static void inputOne(IO &io, StringRef Key, TypeIdSummaryMapTy &V) {
263    TypeIdSummary TId;
264    io.mapRequired(Key.str().c_str(), TId);
265    V.insert({GlobalValue::getGUID(Key), {Key, TId}});
266  }
267  static void output(IO &io, TypeIdSummaryMapTy &V) {
268    for (auto TidIter = V.begin(); TidIter != V.end(); TidIter++)
269      io.mapRequired(TidIter->second.first.c_str(), TidIter->second.second);
270  }
271};
272
273template <> struct MappingTraits<ModuleSummaryIndex> {
274  static void mapping(IO &io, ModuleSummaryIndex& index) {
275    io.mapOptional("GlobalValueMap", index.GlobalValueMap);
276    io.mapOptional("TypeIdMap", index.TypeIdMap);
277    io.mapOptional("WithGlobalValueDeadStripping",
278                   index.WithGlobalValueDeadStripping);
279
280    if (io.outputting()) {
281      std::vector<std::string> CfiFunctionDefs(index.CfiFunctionDefs.begin(),
282                                               index.CfiFunctionDefs.end());
283      io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
284      std::vector<std::string> CfiFunctionDecls(index.CfiFunctionDecls.begin(),
285                                                index.CfiFunctionDecls.end());
286      io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
287    } else {
288      std::vector<std::string> CfiFunctionDefs;
289      io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
290      index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()};
291      std::vector<std::string> CfiFunctionDecls;
292      io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
293      index.CfiFunctionDecls = {CfiFunctionDecls.begin(),
294                                CfiFunctionDecls.end()};
295    }
296  }
297};
298
299} // End yaml namespace
300} // End llvm namespace
301
302#endif
303