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