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 
15 namespace llvm {
16 namespace yaml {
17 
18 template <> 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 
28 template <> 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 
39 template <>
40 struct 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 
53 template <> 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 
62 template <>
63 struct 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 
96 template <> 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 
105 template <> 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 
113 template <>
114 struct 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 
130 template <> 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 
137 struct FunctionSummaryYaml {
138   unsigned Linkage;
139   bool NotEligibleToImport, Live, IsLocal;
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 
151 namespace llvm {
152 namespace yaml {
153 
154 template <> 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 
161 template <> 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 
171 LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId)
172 LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall)
173 
174 namespace llvm {
175 namespace yaml {
176 
177 template <> 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("Refs", summary.Refs);
184     io.mapOptional("TypeTests", summary.TypeTests);
185     io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
186     io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
187     io.mapOptional("TypeTestAssumeConstVCalls",
188                    summary.TypeTestAssumeConstVCalls);
189     io.mapOptional("TypeCheckedLoadConstVCalls",
190                    summary.TypeCheckedLoadConstVCalls);
191   }
192 };
193 
194 } // End yaml namespace
195 } // End llvm namespace
196 
197 LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml)
198 
199 namespace llvm {
200 namespace yaml {
201 
202 // FIXME: Add YAML mappings for the rest of the module summary.
203 template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
204   static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) {
205     std::vector<FunctionSummaryYaml> FSums;
206     io.mapRequired(Key.str().c_str(), FSums);
207     uint64_t KeyInt;
208     if (Key.getAsInteger(0, KeyInt)) {
209       io.setError("key not an integer");
210       return;
211     }
212     if (!V.count(KeyInt))
213       V.emplace(KeyInt, /*IsAnalysis=*/false);
214     auto &Elem = V.find(KeyInt)->second;
215     for (auto &FSum : FSums) {
216       std::vector<ValueInfo> Refs;
217       for (auto &RefGUID : FSum.Refs) {
218         if (!V.count(RefGUID))
219           V.emplace(RefGUID, /*IsAnalysis=*/false);
220         Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID)));
221       }
222       Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>(
223           GlobalValueSummary::GVFlags(
224               static_cast<GlobalValue::LinkageTypes>(FSum.Linkage),
225               FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal),
226           /*NumInsts=*/0, FunctionSummary::FFlags{}, /*EntryCount=*/0, Refs,
227           ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
228           std::move(FSum.TypeTestAssumeVCalls),
229           std::move(FSum.TypeCheckedLoadVCalls),
230           std::move(FSum.TypeTestAssumeConstVCalls),
231           std::move(FSum.TypeCheckedLoadConstVCalls)));
232     }
233   }
234   static void output(IO &io, GlobalValueSummaryMapTy &V) {
235     for (auto &P : V) {
236       std::vector<FunctionSummaryYaml> FSums;
237       for (auto &Sum : P.second.SummaryList) {
238         if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) {
239           std::vector<uint64_t> Refs;
240           for (auto &VI : FSum->refs())
241             Refs.push_back(VI.getGUID());
242           FSums.push_back(FunctionSummaryYaml{
243               FSum->flags().Linkage,
244               static_cast<bool>(FSum->flags().NotEligibleToImport),
245               static_cast<bool>(FSum->flags().Live),
246               static_cast<bool>(FSum->flags().DSOLocal), Refs,
247               FSum->type_tests(), FSum->type_test_assume_vcalls(),
248               FSum->type_checked_load_vcalls(),
249               FSum->type_test_assume_const_vcalls(),
250               FSum->type_checked_load_const_vcalls()});
251           }
252       }
253       if (!FSums.empty())
254         io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
255     }
256   }
257 };
258 
259 template <> struct CustomMappingTraits<TypeIdSummaryMapTy> {
260   static void inputOne(IO &io, StringRef Key, TypeIdSummaryMapTy &V) {
261     TypeIdSummary TId;
262     io.mapRequired(Key.str().c_str(), TId);
263     V.insert({GlobalValue::getGUID(Key), {Key, TId}});
264   }
265   static void output(IO &io, TypeIdSummaryMapTy &V) {
266     for (auto TidIter = V.begin(); TidIter != V.end(); TidIter++)
267       io.mapRequired(TidIter->second.first.c_str(), TidIter->second.second);
268   }
269 };
270 
271 template <> struct MappingTraits<ModuleSummaryIndex> {
272   static void mapping(IO &io, ModuleSummaryIndex& index) {
273     io.mapOptional("GlobalValueMap", index.GlobalValueMap);
274     io.mapOptional("TypeIdMap", index.TypeIdMap);
275     io.mapOptional("WithGlobalValueDeadStripping",
276                    index.WithGlobalValueDeadStripping);
277 
278     if (io.outputting()) {
279       std::vector<std::string> CfiFunctionDefs(index.CfiFunctionDefs.begin(),
280                                                index.CfiFunctionDefs.end());
281       io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
282       std::vector<std::string> CfiFunctionDecls(index.CfiFunctionDecls.begin(),
283                                                 index.CfiFunctionDecls.end());
284       io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
285     } else {
286       std::vector<std::string> CfiFunctionDefs;
287       io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
288       index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()};
289       std::vector<std::string> CfiFunctionDecls;
290       io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
291       index.CfiFunctionDecls = {CfiFunctionDecls.begin(),
292                                 CfiFunctionDecls.end()};
293     }
294   }
295 };
296 
297 } // End yaml namespace
298 } // End llvm namespace
299 
300 #endif
301