aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ProfileData/SampleProfReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ProfileData/SampleProfReader.cpp')
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 204e34b..8a97697 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -30,6 +30,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MD5.h"
@@ -72,6 +73,79 @@ void SampleProfileReader::dump(raw_ostream &OS) {
dumpFunctionProfile(I.first, OS);
}
+static void dumpFunctionProfileJson(const FunctionSamples &S,
+ json::OStream &JOS, bool TopLevel = false) {
+ auto DumpBody = [&](const BodySampleMap &BodySamples) {
+ for (const auto &I : BodySamples) {
+ const LineLocation &Loc = I.first;
+ const SampleRecord &Sample = I.second;
+ JOS.object([&] {
+ JOS.attribute("line", Loc.LineOffset);
+ if (Loc.Discriminator)
+ JOS.attribute("discriminator", Loc.Discriminator);
+ JOS.attribute("samples", Sample.getSamples());
+
+ auto CallTargets = Sample.getSortedCallTargets();
+ if (!CallTargets.empty()) {
+ JOS.attributeArray("calls", [&] {
+ for (const auto &J : CallTargets) {
+ JOS.object([&] {
+ JOS.attribute("function", J.first);
+ JOS.attribute("samples", J.second);
+ });
+ }
+ });
+ }
+ });
+ }
+ };
+
+ auto DumpCallsiteSamples = [&](const CallsiteSampleMap &CallsiteSamples) {
+ for (const auto &I : CallsiteSamples)
+ for (const auto &FS : I.second) {
+ const LineLocation &Loc = I.first;
+ const FunctionSamples &CalleeSamples = FS.second;
+ JOS.object([&] {
+ JOS.attribute("line", Loc.LineOffset);
+ if (Loc.Discriminator)
+ JOS.attribute("discriminator", Loc.Discriminator);
+ JOS.attributeArray(
+ "samples", [&] { dumpFunctionProfileJson(CalleeSamples, JOS); });
+ });
+ }
+ };
+
+ JOS.object([&] {
+ JOS.attribute("name", S.getName());
+ JOS.attribute("total", S.getTotalSamples());
+ if (TopLevel)
+ JOS.attribute("head", S.getHeadSamples());
+
+ const auto &BodySamples = S.getBodySamples();
+ if (!BodySamples.empty())
+ JOS.attributeArray("body", [&] { DumpBody(BodySamples); });
+
+ const auto &CallsiteSamples = S.getCallsiteSamples();
+ if (!CallsiteSamples.empty())
+ JOS.attributeArray("callsites",
+ [&] { DumpCallsiteSamples(CallsiteSamples); });
+ });
+}
+
+/// Dump all the function profiles found on stream \p OS in the JSON format.
+void SampleProfileReader::dumpJson(raw_ostream &OS) {
+ std::vector<NameFunctionSamples> V;
+ sortFuncProfiles(Profiles, V);
+ json::OStream JOS(OS, 2);
+ JOS.arrayBegin();
+ for (const auto &[FC, FS] : V)
+ dumpFunctionProfileJson(*FS, JOS, true);
+ JOS.arrayEnd();
+
+ // Emit a newline character at the end as json::OStream doesn't emit one.
+ OS << "\n";
+}
+
/// Parse \p Input as function head.
///
/// Parse one line of \p Input, and update function name in \p FName,