1 //===-- llvm/ModuleSummaryIndexYAML.h - YAML I/O for summary ----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_IR_MODULESUMMARYINDEXYAML_H 11 #define LLVM_IR_MODULESUMMARYINDEXYAML_H 12 13 #include "llvm/IR/ModuleSummaryIndex.h" 14 #include "llvm/Support/YAMLTraits.h" 15 16 namespace llvm { 17 namespace yaml { 18 19 template <> struct ScalarEnumerationTraits<TypeTestResolution::Kind> { 20 static void enumeration(IO &io, TypeTestResolution::Kind &value) { 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; 140 bool NotEligibleToImport, Live, IsLocal; 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("NotEligibleToImport", summary.NotEligibleToImport); 182 io.mapOptional("Live", summary.Live); 183 io.mapOptional("Local", summary.IsLocal); 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 198 LLVM_YAML_IS_STRING_MAP(TypeIdSummary) 199 LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml) 200 201 namespace llvm { 202 namespace yaml { 203 204 // FIXME: Add YAML mappings for the rest of the module summary. 205 template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { 206 static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) { 207 std::vector<FunctionSummaryYaml> FSums; 208 io.mapRequired(Key.str().c_str(), FSums); 209 uint64_t KeyInt; 210 if (Key.getAsInteger(0, KeyInt)) { 211 io.setError("key not an integer"); 212 return; 213 } 214 if (!V.count(KeyInt)) 215 V.emplace(KeyInt, /*IsAnalysis=*/false); 216 auto &Elem = V.find(KeyInt)->second; 217 for (auto &FSum : FSums) { 218 std::vector<ValueInfo> Refs; 219 for (auto &RefGUID : FSum.Refs) { 220 if (!V.count(RefGUID)) 221 V.emplace(RefGUID, /*IsAnalysis=*/false); 222 Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID))); 223 } 224 Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>( 225 GlobalValueSummary::GVFlags( 226 static_cast<GlobalValue::LinkageTypes>(FSum.Linkage), 227 FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal), 228 0, FunctionSummary::FFlags{}, Refs, 229 ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests), 230 std::move(FSum.TypeTestAssumeVCalls), 231 std::move(FSum.TypeCheckedLoadVCalls), 232 std::move(FSum.TypeTestAssumeConstVCalls), 233 std::move(FSum.TypeCheckedLoadConstVCalls))); 234 } 235 } 236 static void output(IO &io, GlobalValueSummaryMapTy &V) { 237 for (auto &P : V) { 238 std::vector<FunctionSummaryYaml> FSums; 239 for (auto &Sum : P.second.SummaryList) { 240 if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) { 241 std::vector<uint64_t> Refs; 242 for (auto &VI : FSum->refs()) 243 Refs.push_back(VI.getGUID()); 244 FSums.push_back(FunctionSummaryYaml{ 245 FSum->flags().Linkage, 246 static_cast<bool>(FSum->flags().NotEligibleToImport), 247 static_cast<bool>(FSum->flags().Live), 248 static_cast<bool>(FSum->flags().DSOLocal), 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 261 template <> struct MappingTraits<ModuleSummaryIndex> { 262 static void mapping(IO &io, ModuleSummaryIndex& index) { 263 io.mapOptional("GlobalValueMap", index.GlobalValueMap); 264 io.mapOptional("TypeIdMap", index.TypeIdMap); 265 io.mapOptional("WithGlobalValueDeadStripping", 266 index.WithGlobalValueDeadStripping); 267 268 if (io.outputting()) { 269 std::vector<std::string> CfiFunctionDefs(index.CfiFunctionDefs.begin(), 270 index.CfiFunctionDefs.end()); 271 io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); 272 std::vector<std::string> CfiFunctionDecls(index.CfiFunctionDecls.begin(), 273 index.CfiFunctionDecls.end()); 274 io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); 275 } else { 276 std::vector<std::string> CfiFunctionDefs; 277 io.mapOptional("CfiFunctionDefs", CfiFunctionDefs); 278 index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()}; 279 std::vector<std::string> CfiFunctionDecls; 280 io.mapOptional("CfiFunctionDecls", CfiFunctionDecls); 281 index.CfiFunctionDecls = {CfiFunctionDecls.begin(), 282 CfiFunctionDecls.end()}; 283 } 284 } 285 }; 286 287 } // End yaml namespace 288 } // End llvm namespace 289 290 #endif 291