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