1717#include " llvm/ProfileData/InstrProf.h"
1818#include " llvm/ProfileData/PGOCtxProfWriter.h"
1919#include " llvm/Support/Error.h"
20+ #include " llvm/Support/ErrorHandling.h"
21+ #include " llvm/Support/YAMLTraits.h"
22+ #include < iterator>
23+ #include < utility>
2024
2125using namespace llvm ;
2226
@@ -176,3 +180,87 @@ PGOCtxProfileReader::loadContexts() {
176180 }
177181 return std::move (Ret);
178182}
183+
184+ namespace {
185+ // We want to pass `const` values PGOCtxProfContext references to the yaml
186+ // converter, and the regular yaml mapping APIs are designed to handle both
187+ // serialization and deserialization, which prevents using const for
188+ // serialization. Using an intermediate datastructure is overkill, both
189+ // space-wise and design complexity-wise. Instead, we use the lower-level APIs.
190+ void toYaml (yaml::Output &Out, const PGOCtxProfContext &Ctx);
191+
192+ void toYaml (yaml::Output &Out,
193+ const PGOCtxProfContext::CallTargetMapTy &CallTargets) {
194+ Out.beginSequence ();
195+ size_t Index = 0 ;
196+ void *SaveData = nullptr ;
197+ for (const auto &[_, Ctx] : CallTargets) {
198+ Out.preflightElement (Index++, SaveData);
199+ toYaml (Out, Ctx);
200+ Out.postflightElement (nullptr );
201+ }
202+ Out.endSequence ();
203+ }
204+
205+ void toYaml (yaml::Output &Out,
206+ const PGOCtxProfContext::CallsiteMapTy &Callsites) {
207+ auto AllCS =
208+ ::llvm::map_range (Callsites, [](const auto &P) { return P.first ; });
209+ auto MaxIt = ::llvm::max_element (AllCS);
210+ assert (MaxIt != AllCS.end () && " We should have a max value because the "
211+ " callsites collection is not empty." );
212+ void *SaveData = nullptr ;
213+ Out.beginSequence ();
214+ for (auto I = 0U ; I <= *MaxIt; ++I) {
215+ Out.preflightElement (I, SaveData);
216+ auto It = Callsites.find (I);
217+ if (It == Callsites.end ()) {
218+ // This will produce a `[ ]` sequence, which is what we want here.
219+ Out.beginFlowSequence ();
220+ Out.endFlowSequence ();
221+ } else {
222+ toYaml (Out, It->second );
223+ }
224+ Out.postflightElement (nullptr );
225+ }
226+ Out.endSequence ();
227+ }
228+
229+ void toYaml (yaml::Output &Out, const PGOCtxProfContext &Ctx) {
230+ yaml::EmptyContext Empty;
231+ Out.beginMapping ();
232+ void *SaveInfo = nullptr ;
233+ bool UseDefault = false ;
234+ {
235+ Out.preflightKey (" Guid" , /* Required=*/ true , /* SameAsDefault=*/ false ,
236+ UseDefault, SaveInfo);
237+ auto Guid = Ctx.guid ();
238+ yaml::yamlize (Out, Guid, true , Empty);
239+ Out.postflightKey (nullptr );
240+ }
241+ {
242+ Out.preflightKey (" Counters" , true , false , UseDefault, SaveInfo);
243+ Out.beginFlowSequence ();
244+ for (size_t I = 0U , E = Ctx.counters ().size (); I < E; ++I) {
245+ Out.preflightFlowElement (I, SaveInfo);
246+ uint64_t V = Ctx.counters ()[I];
247+ yaml::yamlize (Out, V, true , Empty);
248+ Out.postflightFlowElement (SaveInfo);
249+ }
250+ Out.endFlowSequence ();
251+ Out.postflightKey (nullptr );
252+ }
253+ if (!Ctx.callsites ().empty ()) {
254+ Out.preflightKey (" Callsites" , true , false , UseDefault, SaveInfo);
255+ toYaml (Out, Ctx.callsites ());
256+ Out.postflightKey (nullptr );
257+ }
258+ Out.endMapping ();
259+ }
260+ } // namespace
261+
262+ void llvm::convertToYaml (raw_ostream &OS,
263+ const PGOCtxProfContext::CallTargetMapTy &Profiles) {
264+ yaml::Output Out (OS);
265+ toYaml (Out, Profiles);
266+ }
0 commit comments