xref: /freebsd-src/contrib/llvm-project/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the DIPrinter class, which is responsible for printing
100b57cec5SDimitry Andric // structures defined in DebugInfo/DIContext.h
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/DIContext.h"
170b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
180b57cec5SDimitry Andric #include "llvm/Support/Format.h"
190b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <algorithm>
220b57cec5SDimitry Andric #include <cmath>
230b57cec5SDimitry Andric #include <cstddef>
240b57cec5SDimitry Andric #include <cstdint>
250b57cec5SDimitry Andric #include <memory>
260b57cec5SDimitry Andric #include <string>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace llvm {
290b57cec5SDimitry Andric namespace symbolize {
300b57cec5SDimitry Andric 
31fe6060f1SDimitry Andric class SourceCode {
32fe6060f1SDimitry Andric   std::unique_ptr<MemoryBuffer> MemBuf;
330b57cec5SDimitry Andric 
34bdd1243dSDimitry Andric   std::optional<StringRef>
load(StringRef FileName,const std::optional<StringRef> & EmbeddedSource)35bdd1243dSDimitry Andric   load(StringRef FileName, const std::optional<StringRef> &EmbeddedSource) {
36fe6060f1SDimitry Andric     if (Lines <= 0)
37bdd1243dSDimitry Andric       return std::nullopt;
38fe6060f1SDimitry Andric 
39fe6060f1SDimitry Andric     if (EmbeddedSource)
40fe6060f1SDimitry Andric       return EmbeddedSource;
41fe6060f1SDimitry Andric     else {
420b57cec5SDimitry Andric       ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
430b57cec5SDimitry Andric           MemoryBuffer::getFile(FileName);
440b57cec5SDimitry Andric       if (!BufOrErr)
45bdd1243dSDimitry Andric         return std::nullopt;
46fe6060f1SDimitry Andric       MemBuf = std::move(*BufOrErr);
47fe6060f1SDimitry Andric       return MemBuf->getBuffer();
48fe6060f1SDimitry Andric     }
49fe6060f1SDimitry Andric   }
50fe6060f1SDimitry Andric 
pruneSource(const std::optional<StringRef> & Source)51bdd1243dSDimitry Andric   std::optional<StringRef> pruneSource(const std::optional<StringRef> &Source) {
52fe6060f1SDimitry Andric     if (!Source)
53bdd1243dSDimitry Andric       return std::nullopt;
54fe6060f1SDimitry Andric     size_t FirstLinePos = StringRef::npos, Pos = 0;
55fe6060f1SDimitry Andric     for (int64_t L = 1; L <= LastLine; ++L, ++Pos) {
56fe6060f1SDimitry Andric       if (L == FirstLine)
57fe6060f1SDimitry Andric         FirstLinePos = Pos;
58fe6060f1SDimitry Andric       Pos = Source->find('\n', Pos);
59fe6060f1SDimitry Andric       if (Pos == StringRef::npos)
60fe6060f1SDimitry Andric         break;
61fe6060f1SDimitry Andric     }
62fe6060f1SDimitry Andric     if (FirstLinePos == StringRef::npos)
63bdd1243dSDimitry Andric       return std::nullopt;
64fe6060f1SDimitry Andric     return Source->substr(FirstLinePos, (Pos == StringRef::npos)
65fe6060f1SDimitry Andric                                             ? StringRef::npos
66fe6060f1SDimitry Andric                                             : Pos - FirstLinePos);
67fe6060f1SDimitry Andric   }
68fe6060f1SDimitry Andric 
69fe6060f1SDimitry Andric public:
70fe6060f1SDimitry Andric   const int64_t Line;
71fe6060f1SDimitry Andric   const int Lines;
72fe6060f1SDimitry Andric   const int64_t FirstLine;
73fe6060f1SDimitry Andric   const int64_t LastLine;
74bdd1243dSDimitry Andric   const std::optional<StringRef> PrunedSource;
75fe6060f1SDimitry Andric 
SourceCode(StringRef FileName,int64_t Line,int Lines,const std::optional<StringRef> & EmbeddedSource=std::optional<StringRef> ())76bdd1243dSDimitry Andric   SourceCode(StringRef FileName, int64_t Line, int Lines,
77bdd1243dSDimitry Andric              const std::optional<StringRef> &EmbeddedSource =
78bdd1243dSDimitry Andric                  std::optional<StringRef>())
79fe6060f1SDimitry Andric       : Line(Line), Lines(Lines),
80fe6060f1SDimitry Andric         FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)),
81fe6060f1SDimitry Andric         LastLine(FirstLine + Lines - 1),
82fe6060f1SDimitry Andric         PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {}
83fe6060f1SDimitry Andric 
format(raw_ostream & OS)84fe6060f1SDimitry Andric   void format(raw_ostream &OS) {
85fe6060f1SDimitry Andric     if (!PrunedSource)
860b57cec5SDimitry Andric       return;
870b57cec5SDimitry Andric     size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
88fe6060f1SDimitry Andric     int64_t L = FirstLine;
89fe6060f1SDimitry Andric     for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) {
90fe6060f1SDimitry Andric       size_t PosEnd = PrunedSource->find('\n', Pos);
91fe6060f1SDimitry Andric       StringRef String = PrunedSource->substr(
92fe6060f1SDimitry Andric           Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos));
93*5f757f3fSDimitry Andric       if (String.ends_with("\r"))
94fe6060f1SDimitry Andric         String = String.drop_back(1);
950b57cec5SDimitry Andric       OS << format_decimal(L, MaxLineNumberWidth);
960b57cec5SDimitry Andric       if (L == Line)
970b57cec5SDimitry Andric         OS << " >: ";
980b57cec5SDimitry Andric       else
990b57cec5SDimitry Andric         OS << "  : ";
100fe6060f1SDimitry Andric       OS << String << '\n';
101fe6060f1SDimitry Andric       if (PosEnd == StringRef::npos)
102fe6060f1SDimitry Andric         break;
103fe6060f1SDimitry Andric       Pos = PosEnd + 1;
1040b57cec5SDimitry Andric     }
1050b57cec5SDimitry Andric   }
106fe6060f1SDimitry Andric };
107fe6060f1SDimitry Andric 
printHeader(std::optional<uint64_t> Address)108*5f757f3fSDimitry Andric void PlainPrinterBase::printHeader(std::optional<uint64_t> Address) {
109*5f757f3fSDimitry Andric   if (Address.has_value() && Config.PrintAddress) {
110fe6060f1SDimitry Andric     OS << "0x";
111*5f757f3fSDimitry Andric     OS.write_hex(*Address);
112fe6060f1SDimitry Andric     StringRef Delimiter = Config.Pretty ? ": " : "\n";
113fe6060f1SDimitry Andric     OS << Delimiter;
114fe6060f1SDimitry Andric   }
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
117fe6060f1SDimitry Andric // Prints source code around in the FileName the Line.
printContext(SourceCode SourceCode)118fe6060f1SDimitry Andric void PlainPrinterBase::printContext(SourceCode SourceCode) {
119fe6060f1SDimitry Andric   SourceCode.format(OS);
120fe6060f1SDimitry Andric }
121fe6060f1SDimitry Andric 
printFunctionName(StringRef FunctionName,bool Inlined)122fe6060f1SDimitry Andric void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
123fe6060f1SDimitry Andric   if (Config.PrintFunctions) {
1248bcb0991SDimitry Andric     if (FunctionName == DILineInfo::BadString)
1258bcb0991SDimitry Andric       FunctionName = DILineInfo::Addr2LineBadString;
126fe6060f1SDimitry Andric     StringRef Delimiter = Config.Pretty ? " at " : "\n";
127fe6060f1SDimitry Andric     StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : "";
1280b57cec5SDimitry Andric     OS << Prefix << FunctionName << Delimiter;
1290b57cec5SDimitry Andric   }
130fe6060f1SDimitry Andric }
131fe6060f1SDimitry Andric 
printSimpleLocation(StringRef Filename,const DILineInfo & Info)132fe6060f1SDimitry Andric void LLVMPrinter::printSimpleLocation(StringRef Filename,
133fe6060f1SDimitry Andric                                       const DILineInfo &Info) {
134fe6060f1SDimitry Andric   OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
135fe6060f1SDimitry Andric   printContext(
136fe6060f1SDimitry Andric       SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
137fe6060f1SDimitry Andric }
138fe6060f1SDimitry Andric 
printSimpleLocation(StringRef Filename,const DILineInfo & Info)139fe6060f1SDimitry Andric void GNUPrinter::printSimpleLocation(StringRef Filename,
140fe6060f1SDimitry Andric                                      const DILineInfo &Info) {
141fe6060f1SDimitry Andric   OS << Filename << ':' << Info.Line;
142fe6060f1SDimitry Andric   if (Info.Discriminator)
143fe6060f1SDimitry Andric     OS << " (discriminator " << Info.Discriminator << ')';
144fe6060f1SDimitry Andric   OS << '\n';
145fe6060f1SDimitry Andric   printContext(
146fe6060f1SDimitry Andric       SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
147fe6060f1SDimitry Andric }
148fe6060f1SDimitry Andric 
printVerbose(StringRef Filename,const DILineInfo & Info)149fe6060f1SDimitry Andric void PlainPrinterBase::printVerbose(StringRef Filename,
150fe6060f1SDimitry Andric                                     const DILineInfo &Info) {
151fe6060f1SDimitry Andric   OS << "  Filename: " << Filename << '\n';
152fe6060f1SDimitry Andric   if (Info.StartLine) {
153fe6060f1SDimitry Andric     OS << "  Function start filename: " << Info.StartFileName << '\n';
154fe6060f1SDimitry Andric     OS << "  Function start line: " << Info.StartLine << '\n';
155fe6060f1SDimitry Andric   }
156fe6060f1SDimitry Andric   printStartAddress(Info);
157fe6060f1SDimitry Andric   OS << "  Line: " << Info.Line << '\n';
158fe6060f1SDimitry Andric   OS << "  Column: " << Info.Column << '\n';
159fe6060f1SDimitry Andric   if (Info.Discriminator)
160fe6060f1SDimitry Andric     OS << "  Discriminator: " << Info.Discriminator << '\n';
161fe6060f1SDimitry Andric }
162fe6060f1SDimitry Andric 
printStartAddress(const DILineInfo & Info)163fe6060f1SDimitry Andric void LLVMPrinter::printStartAddress(const DILineInfo &Info) {
164fe6060f1SDimitry Andric   if (Info.StartAddress) {
165fe6060f1SDimitry Andric     OS << "  Function start address: 0x";
166fe6060f1SDimitry Andric     OS.write_hex(*Info.StartAddress);
167fe6060f1SDimitry Andric     OS << '\n';
168fe6060f1SDimitry Andric   }
169fe6060f1SDimitry Andric }
170fe6060f1SDimitry Andric 
printFooter()171fe6060f1SDimitry Andric void LLVMPrinter::printFooter() { OS << '\n'; }
172fe6060f1SDimitry Andric 
print(const DILineInfo & Info,bool Inlined)173fe6060f1SDimitry Andric void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) {
174fe6060f1SDimitry Andric   printFunctionName(Info.FunctionName, Inlined);
175fe6060f1SDimitry Andric   StringRef Filename = Info.FileName;
1768bcb0991SDimitry Andric   if (Filename == DILineInfo::BadString)
1778bcb0991SDimitry Andric     Filename = DILineInfo::Addr2LineBadString;
178fe6060f1SDimitry Andric   if (Config.Verbose)
179fe6060f1SDimitry Andric     printVerbose(Filename, Info);
180fe6060f1SDimitry Andric   else
181fe6060f1SDimitry Andric     printSimpleLocation(Filename, Info);
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
print(const Request & Request,const DILineInfo & Info)184fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) {
185*5f757f3fSDimitry Andric   printHeader(Request.Address);
1860b57cec5SDimitry Andric   print(Info, false);
187fe6060f1SDimitry Andric   printFooter();
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
print(const Request & Request,const DIInliningInfo & Info)190fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request,
191fe6060f1SDimitry Andric                              const DIInliningInfo &Info) {
192fe6060f1SDimitry Andric   printHeader(*Request.Address);
1930b57cec5SDimitry Andric   uint32_t FramesNum = Info.getNumberOfFrames();
194fe6060f1SDimitry Andric   if (FramesNum == 0)
1950b57cec5SDimitry Andric     print(DILineInfo(), false);
196fe6060f1SDimitry Andric   else
197fe6060f1SDimitry Andric     for (uint32_t I = 0; I < FramesNum; ++I)
198fe6060f1SDimitry Andric       print(Info.getFrame(I), I > 0);
199fe6060f1SDimitry Andric   printFooter();
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
print(const Request & Request,const DIGlobal & Global)202fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) {
203fe6060f1SDimitry Andric   printHeader(*Request.Address);
204fe6060f1SDimitry Andric   StringRef Name = Global.Name;
2058bcb0991SDimitry Andric   if (Name == DILineInfo::BadString)
2068bcb0991SDimitry Andric     Name = DILineInfo::Addr2LineBadString;
2070b57cec5SDimitry Andric   OS << Name << "\n";
2080b57cec5SDimitry Andric   OS << Global.Start << " " << Global.Size << "\n";
20981ad6265SDimitry Andric   if (Global.DeclFile.empty())
21081ad6265SDimitry Andric     OS << "??:?\n";
21181ad6265SDimitry Andric   else
21281ad6265SDimitry Andric     OS << Global.DeclFile << ":" << Global.DeclLine << "\n";
213fe6060f1SDimitry Andric   printFooter();
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
print(const Request & Request,const std::vector<DILocal> & Locals)216fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request,
217fe6060f1SDimitry Andric                              const std::vector<DILocal> &Locals) {
218fe6060f1SDimitry Andric   printHeader(*Request.Address);
219fe6060f1SDimitry Andric   if (Locals.empty())
220fe6060f1SDimitry Andric     OS << DILineInfo::Addr2LineBadString << '\n';
221480093f4SDimitry Andric   else
222fe6060f1SDimitry Andric     for (const DILocal &L : Locals) {
223fe6060f1SDimitry Andric       if (L.FunctionName.empty())
224fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
225480093f4SDimitry Andric       else
226fe6060f1SDimitry Andric         OS << L.FunctionName;
227fe6060f1SDimitry Andric       OS << '\n';
228480093f4SDimitry Andric 
229fe6060f1SDimitry Andric       if (L.Name.empty())
230fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
2310b57cec5SDimitry Andric       else
232fe6060f1SDimitry Andric         OS << L.Name;
233fe6060f1SDimitry Andric       OS << '\n';
234480093f4SDimitry Andric 
235fe6060f1SDimitry Andric       if (L.DeclFile.empty())
236fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
237fe6060f1SDimitry Andric       else
238fe6060f1SDimitry Andric         OS << L.DeclFile;
239fe6060f1SDimitry Andric 
240fe6060f1SDimitry Andric       OS << ':' << L.DeclLine << '\n';
241fe6060f1SDimitry Andric 
242fe6060f1SDimitry Andric       if (L.FrameOffset)
243fe6060f1SDimitry Andric         OS << *L.FrameOffset;
244fe6060f1SDimitry Andric       else
245fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
246fe6060f1SDimitry Andric       OS << ' ';
247fe6060f1SDimitry Andric 
248fe6060f1SDimitry Andric       if (L.Size)
249fe6060f1SDimitry Andric         OS << *L.Size;
250fe6060f1SDimitry Andric       else
251fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
252fe6060f1SDimitry Andric       OS << ' ';
253fe6060f1SDimitry Andric 
254fe6060f1SDimitry Andric       if (L.TagOffset)
255fe6060f1SDimitry Andric         OS << *L.TagOffset;
256fe6060f1SDimitry Andric       else
257fe6060f1SDimitry Andric         OS << DILineInfo::Addr2LineBadString;
258fe6060f1SDimitry Andric       OS << '\n';
259fe6060f1SDimitry Andric     }
260fe6060f1SDimitry Andric   printFooter();
261fe6060f1SDimitry Andric }
262fe6060f1SDimitry Andric 
print(const Request & Request,const std::vector<DILineInfo> & Locations)263*5f757f3fSDimitry Andric void PlainPrinterBase::print(const Request &Request,
264*5f757f3fSDimitry Andric                              const std::vector<DILineInfo> &Locations) {
265*5f757f3fSDimitry Andric   if (Locations.empty()) {
266*5f757f3fSDimitry Andric     print(Request, DILineInfo());
267*5f757f3fSDimitry Andric   } else {
268*5f757f3fSDimitry Andric     for (const DILineInfo &L : Locations)
269*5f757f3fSDimitry Andric       print(L, false);
270*5f757f3fSDimitry Andric     printFooter();
271*5f757f3fSDimitry Andric   }
272fe6060f1SDimitry Andric }
273fe6060f1SDimitry Andric 
printError(const Request & Request,const ErrorInfoBase & ErrorInfo)274fe6060f1SDimitry Andric bool PlainPrinterBase::printError(const Request &Request,
27506c3fb27SDimitry Andric                                   const ErrorInfoBase &ErrorInfo) {
27606c3fb27SDimitry Andric   ErrHandler(ErrorInfo, Request.ModuleName);
277fe6060f1SDimitry Andric   // Print an empty struct too.
278fe6060f1SDimitry Andric   return true;
279fe6060f1SDimitry Andric }
280fe6060f1SDimitry Andric 
toHex(uint64_t V)281fe6060f1SDimitry Andric static std::string toHex(uint64_t V) {
282fe6060f1SDimitry Andric   return ("0x" + Twine::utohexstr(V)).str();
283fe6060f1SDimitry Andric }
284fe6060f1SDimitry Andric 
toJSON(const Request & Request,StringRef ErrorMsg="")285fe6060f1SDimitry Andric static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") {
286fe6060f1SDimitry Andric   json::Object Json({{"ModuleName", Request.ModuleName.str()}});
287*5f757f3fSDimitry Andric   if (!Request.Symbol.empty())
288*5f757f3fSDimitry Andric     Json["SymName"] = Request.Symbol.str();
289fe6060f1SDimitry Andric   if (Request.Address)
290fe6060f1SDimitry Andric     Json["Address"] = toHex(*Request.Address);
291fe6060f1SDimitry Andric   if (!ErrorMsg.empty())
292fe6060f1SDimitry Andric     Json["Error"] = json::Object({{"Message", ErrorMsg.str()}});
293fe6060f1SDimitry Andric   return Json;
294fe6060f1SDimitry Andric }
295fe6060f1SDimitry Andric 
toJSON(const DILineInfo & LineInfo)29606c3fb27SDimitry Andric static json::Object toJSON(const DILineInfo &LineInfo) {
29706c3fb27SDimitry Andric   return json::Object(
298fe6060f1SDimitry Andric       {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString
299fe6060f1SDimitry Andric                             ? LineInfo.FunctionName
300fe6060f1SDimitry Andric                             : ""},
301fe6060f1SDimitry Andric        {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString
302fe6060f1SDimitry Andric                              ? LineInfo.StartFileName
303fe6060f1SDimitry Andric                              : ""},
304fe6060f1SDimitry Andric        {"StartLine", LineInfo.StartLine},
305fe6060f1SDimitry Andric        {"StartAddress",
306fe6060f1SDimitry Andric         LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""},
307fe6060f1SDimitry Andric        {"FileName",
308fe6060f1SDimitry Andric         LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""},
309fe6060f1SDimitry Andric        {"Line", LineInfo.Line},
310fe6060f1SDimitry Andric        {"Column", LineInfo.Column},
311fe6060f1SDimitry Andric        {"Discriminator", LineInfo.Discriminator}});
31206c3fb27SDimitry Andric }
31306c3fb27SDimitry Andric 
print(const Request & Request,const DILineInfo & Info)31406c3fb27SDimitry Andric void JSONPrinter::print(const Request &Request, const DILineInfo &Info) {
31506c3fb27SDimitry Andric   DIInliningInfo InliningInfo;
31606c3fb27SDimitry Andric   InliningInfo.addFrame(Info);
31706c3fb27SDimitry Andric   print(Request, InliningInfo);
31806c3fb27SDimitry Andric }
31906c3fb27SDimitry Andric 
print(const Request & Request,const DIInliningInfo & Info)32006c3fb27SDimitry Andric void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) {
32106c3fb27SDimitry Andric   json::Array Array;
32206c3fb27SDimitry Andric   for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) {
32306c3fb27SDimitry Andric     const DILineInfo &LineInfo = Info.getFrame(I);
32406c3fb27SDimitry Andric     json::Object Object = toJSON(LineInfo);
325fe6060f1SDimitry Andric     SourceCode SourceCode(LineInfo.FileName, LineInfo.Line,
326fe6060f1SDimitry Andric                           Config.SourceContextLines, LineInfo.Source);
327fe6060f1SDimitry Andric     std::string FormattedSource;
328fe6060f1SDimitry Andric     raw_string_ostream Stream(FormattedSource);
329fe6060f1SDimitry Andric     SourceCode.format(Stream);
330fe6060f1SDimitry Andric     if (!FormattedSource.empty())
331fe6060f1SDimitry Andric       Object["Source"] = std::move(FormattedSource);
332fe6060f1SDimitry Andric     Array.push_back(std::move(Object));
333fe6060f1SDimitry Andric   }
334fe6060f1SDimitry Andric   json::Object Json = toJSON(Request);
335fe6060f1SDimitry Andric   Json["Symbol"] = std::move(Array);
336fe6060f1SDimitry Andric   if (ObjectList)
337fe6060f1SDimitry Andric     ObjectList->push_back(std::move(Json));
338fe6060f1SDimitry Andric   else
339fe6060f1SDimitry Andric     printJSON(std::move(Json));
340fe6060f1SDimitry Andric }
341fe6060f1SDimitry Andric 
print(const Request & Request,const DIGlobal & Global)342fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIGlobal &Global) {
343fe6060f1SDimitry Andric   json::Object Data(
344fe6060f1SDimitry Andric       {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""},
345fe6060f1SDimitry Andric        {"Start", toHex(Global.Start)},
346fe6060f1SDimitry Andric        {"Size", toHex(Global.Size)}});
347fe6060f1SDimitry Andric   json::Object Json = toJSON(Request);
348fe6060f1SDimitry Andric   Json["Data"] = std::move(Data);
349fe6060f1SDimitry Andric   if (ObjectList)
350fe6060f1SDimitry Andric     ObjectList->push_back(std::move(Json));
351fe6060f1SDimitry Andric   else
352fe6060f1SDimitry Andric     printJSON(std::move(Json));
353fe6060f1SDimitry Andric }
354fe6060f1SDimitry Andric 
print(const Request & Request,const std::vector<DILocal> & Locals)355fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request,
356fe6060f1SDimitry Andric                         const std::vector<DILocal> &Locals) {
357fe6060f1SDimitry Andric   json::Array Frame;
358fe6060f1SDimitry Andric   for (const DILocal &Local : Locals) {
359fe6060f1SDimitry Andric     json::Object FrameObject(
360fe6060f1SDimitry Andric         {{"FunctionName", Local.FunctionName},
361fe6060f1SDimitry Andric          {"Name", Local.Name},
362fe6060f1SDimitry Andric          {"DeclFile", Local.DeclFile},
363fe6060f1SDimitry Andric          {"DeclLine", int64_t(Local.DeclLine)},
364fe6060f1SDimitry Andric          {"Size", Local.Size ? toHex(*Local.Size) : ""},
365fe6060f1SDimitry Andric          {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}});
3660b57cec5SDimitry Andric     if (Local.FrameOffset)
367fe6060f1SDimitry Andric       FrameObject["FrameOffset"] = *Local.FrameOffset;
368fe6060f1SDimitry Andric     Frame.push_back(std::move(FrameObject));
369fe6060f1SDimitry Andric   }
370fe6060f1SDimitry Andric   json::Object Json = toJSON(Request);
371fe6060f1SDimitry Andric   Json["Frame"] = std::move(Frame);
372fe6060f1SDimitry Andric   if (ObjectList)
373fe6060f1SDimitry Andric     ObjectList->push_back(std::move(Json));
3740b57cec5SDimitry Andric   else
375fe6060f1SDimitry Andric     printJSON(std::move(Json));
376fe6060f1SDimitry Andric }
377480093f4SDimitry Andric 
print(const Request & Request,const std::vector<DILineInfo> & Locations)378*5f757f3fSDimitry Andric void JSONPrinter::print(const Request &Request,
379*5f757f3fSDimitry Andric                         const std::vector<DILineInfo> &Locations) {
380*5f757f3fSDimitry Andric   json::Array Definitions;
381*5f757f3fSDimitry Andric   for (const DILineInfo &L : Locations)
382*5f757f3fSDimitry Andric     Definitions.push_back(toJSON(L));
383*5f757f3fSDimitry Andric   json::Object Json = toJSON(Request);
384*5f757f3fSDimitry Andric   Json["Loc"] = std::move(Definitions);
385*5f757f3fSDimitry Andric   if (ObjectList)
386*5f757f3fSDimitry Andric     ObjectList->push_back(std::move(Json));
387*5f757f3fSDimitry Andric   else
388*5f757f3fSDimitry Andric     printJSON(std::move(Json));
389fe6060f1SDimitry Andric }
390480093f4SDimitry Andric 
printError(const Request & Request,const ErrorInfoBase & ErrorInfo)391fe6060f1SDimitry Andric bool JSONPrinter::printError(const Request &Request,
39206c3fb27SDimitry Andric                              const ErrorInfoBase &ErrorInfo) {
393fe6060f1SDimitry Andric   json::Object Json = toJSON(Request, ErrorInfo.message());
394fe6060f1SDimitry Andric   if (ObjectList)
395fe6060f1SDimitry Andric     ObjectList->push_back(std::move(Json));
3960b57cec5SDimitry Andric   else
397fe6060f1SDimitry Andric     printJSON(std::move(Json));
398fe6060f1SDimitry Andric   return false;
399fe6060f1SDimitry Andric }
400fe6060f1SDimitry Andric 
listBegin()401fe6060f1SDimitry Andric void JSONPrinter::listBegin() {
402fe6060f1SDimitry Andric   assert(!ObjectList);
403fe6060f1SDimitry Andric   ObjectList = std::make_unique<json::Array>();
404fe6060f1SDimitry Andric }
405fe6060f1SDimitry Andric 
listEnd()406fe6060f1SDimitry Andric void JSONPrinter::listEnd() {
407fe6060f1SDimitry Andric   assert(ObjectList);
408fe6060f1SDimitry Andric   printJSON(std::move(*ObjectList));
409fe6060f1SDimitry Andric   ObjectList.reset();
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric } // end namespace symbolize
4130b57cec5SDimitry Andric } // end namespace llvm
414