1d6aa8202SAlexey Samsonov //===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
2d6aa8202SAlexey Samsonov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d6aa8202SAlexey Samsonov //
7d6aa8202SAlexey Samsonov //===----------------------------------------------------------------------===//
8d6aa8202SAlexey Samsonov //
9d6aa8202SAlexey Samsonov // This file defines the DIPrinter class, which is responsible for printing
10d6aa8202SAlexey Samsonov // structures defined in DebugInfo/DIContext.h
11d6aa8202SAlexey Samsonov //
12d6aa8202SAlexey Samsonov //===----------------------------------------------------------------------===//
13d6aa8202SAlexey Samsonov
14d6aa8202SAlexey Samsonov #include "llvm/DebugInfo/Symbolize/DIPrinter.h"
15417d4c50SEugene Zelenko #include "llvm/ADT/StringRef.h"
16d6aa8202SAlexey Samsonov #include "llvm/DebugInfo/DIContext.h"
17417d4c50SEugene Zelenko #include "llvm/Support/ErrorOr.h"
18417d4c50SEugene Zelenko #include "llvm/Support/Format.h"
19417d4c50SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
20417d4c50SEugene Zelenko #include "llvm/Support/raw_ostream.h"
21417d4c50SEugene Zelenko #include <algorithm>
22417d4c50SEugene Zelenko #include <cmath>
23417d4c50SEugene Zelenko #include <cstddef>
24417d4c50SEugene Zelenko #include <cstdint>
25417d4c50SEugene Zelenko #include <memory>
26417d4c50SEugene Zelenko #include <string>
27d6aa8202SAlexey Samsonov
28d6aa8202SAlexey Samsonov namespace llvm {
29d6aa8202SAlexey Samsonov namespace symbolize {
30d6aa8202SAlexey Samsonov
3188a8965aSAlex Orlov class SourceCode {
3288a8965aSAlex Orlov std::unique_ptr<MemoryBuffer> MemBuf;
3388a8965aSAlex Orlov
load(StringRef FileName,const Optional<StringRef> & EmbeddedSource)34fb28d6fbSKazu Hirata Optional<StringRef> load(StringRef FileName,
3588a8965aSAlex Orlov const Optional<StringRef> &EmbeddedSource) {
3688a8965aSAlex Orlov if (Lines <= 0)
3788a8965aSAlex Orlov return None;
3888a8965aSAlex Orlov
3988a8965aSAlex Orlov if (EmbeddedSource)
4088a8965aSAlex Orlov return EmbeddedSource;
4188a8965aSAlex Orlov else {
4288a8965aSAlex Orlov ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
4388a8965aSAlex Orlov MemoryBuffer::getFile(FileName);
4488a8965aSAlex Orlov if (!BufOrErr)
4588a8965aSAlex Orlov return None;
4688a8965aSAlex Orlov MemBuf = std::move(*BufOrErr);
4788a8965aSAlex Orlov return MemBuf->getBuffer();
4888a8965aSAlex Orlov }
4988a8965aSAlex Orlov }
5088a8965aSAlex Orlov
pruneSource(const Optional<StringRef> & Source)51fb28d6fbSKazu Hirata Optional<StringRef> pruneSource(const Optional<StringRef> &Source) {
5288a8965aSAlex Orlov if (!Source)
5388a8965aSAlex Orlov return None;
5488a8965aSAlex Orlov size_t FirstLinePos = StringRef::npos, Pos = 0;
5588a8965aSAlex Orlov for (int64_t L = 1; L <= LastLine; ++L, ++Pos) {
5688a8965aSAlex Orlov if (L == FirstLine)
5788a8965aSAlex Orlov FirstLinePos = Pos;
5888a8965aSAlex Orlov Pos = Source->find('\n', Pos);
5988a8965aSAlex Orlov if (Pos == StringRef::npos)
6088a8965aSAlex Orlov break;
6188a8965aSAlex Orlov }
6288a8965aSAlex Orlov if (FirstLinePos == StringRef::npos)
6388a8965aSAlex Orlov return None;
6488a8965aSAlex Orlov return Source->substr(FirstLinePos, (Pos == StringRef::npos)
6588a8965aSAlex Orlov ? StringRef::npos
6688a8965aSAlex Orlov : Pos - FirstLinePos);
6788a8965aSAlex Orlov }
6888a8965aSAlex Orlov
6988a8965aSAlex Orlov public:
7088a8965aSAlex Orlov const int64_t Line;
7188a8965aSAlex Orlov const int Lines;
7288a8965aSAlex Orlov const int64_t FirstLine;
7388a8965aSAlex Orlov const int64_t LastLine;
7488a8965aSAlex Orlov const Optional<StringRef> PrunedSource;
7588a8965aSAlex Orlov
SourceCode(StringRef FileName,int64_t Line,int Lines,const Optional<StringRef> & EmbeddedSource=Optional<StringRef> (None))7688a8965aSAlex Orlov SourceCode(
7788a8965aSAlex Orlov StringRef FileName, int64_t Line, int Lines,
7888a8965aSAlex Orlov const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None))
7988a8965aSAlex Orlov : Line(Line), Lines(Lines),
8088a8965aSAlex Orlov FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)),
8188a8965aSAlex Orlov LastLine(FirstLine + Lines - 1),
8288a8965aSAlex Orlov PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {}
83752385b1SAlex Orlov
format(raw_ostream & OS)84752385b1SAlex Orlov void format(raw_ostream &OS) {
85752385b1SAlex Orlov if (!PrunedSource)
86752385b1SAlex Orlov return;
87752385b1SAlex Orlov size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine));
88752385b1SAlex Orlov int64_t L = FirstLine;
89752385b1SAlex Orlov for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) {
90752385b1SAlex Orlov size_t PosEnd = PrunedSource->find('\n', Pos);
91752385b1SAlex Orlov StringRef String = PrunedSource->substr(
92752385b1SAlex Orlov Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos));
93752385b1SAlex Orlov if (String.endswith("\r"))
94752385b1SAlex Orlov String = String.drop_back(1);
95752385b1SAlex Orlov OS << format_decimal(L, MaxLineNumberWidth);
96752385b1SAlex Orlov if (L == Line)
97752385b1SAlex Orlov OS << " >: ";
98752385b1SAlex Orlov else
99752385b1SAlex Orlov OS << " : ";
100752385b1SAlex Orlov OS << String << '\n';
101752385b1SAlex Orlov if (PosEnd == StringRef::npos)
102752385b1SAlex Orlov break;
103752385b1SAlex Orlov Pos = PosEnd + 1;
104752385b1SAlex Orlov }
105752385b1SAlex Orlov }
10688a8965aSAlex Orlov };
10788a8965aSAlex Orlov
printHeader(uint64_t Address)1085f57793cSAlex Orlov void PlainPrinterBase::printHeader(uint64_t Address) {
1095f57793cSAlex Orlov if (Config.PrintAddress) {
1105f57793cSAlex Orlov OS << "0x";
1115f57793cSAlex Orlov OS.write_hex(Address);
1125f57793cSAlex Orlov StringRef Delimiter = Config.Pretty ? ": " : "\n";
1135f57793cSAlex Orlov OS << Delimiter;
1145f57793cSAlex Orlov }
1155f57793cSAlex Orlov }
1165f57793cSAlex Orlov
11717dbc283SMike Aizatsky // Prints source code around in the FileName the Line.
printContext(SourceCode SourceCode)11888a8965aSAlex Orlov void PlainPrinterBase::printContext(SourceCode SourceCode) {
119752385b1SAlex Orlov SourceCode.format(OS);
12017dbc283SMike Aizatsky }
12117dbc283SMike Aizatsky
printFunctionName(StringRef FunctionName,bool Inlined)1225f57793cSAlex Orlov void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) {
1235f57793cSAlex Orlov if (Config.PrintFunctions) {
1249abf668cSMichael Pozulp if (FunctionName == DILineInfo::BadString)
1259abf668cSMichael Pozulp FunctionName = DILineInfo::Addr2LineBadString;
1265f57793cSAlex Orlov StringRef Delimiter = Config.Pretty ? " at " : "\n";
1275f57793cSAlex Orlov StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : "";
128bdce12a0SHemant Kulkarni OS << Prefix << FunctionName << Delimiter;
129d6aa8202SAlexey Samsonov }
1305f57793cSAlex Orlov }
1315f57793cSAlex Orlov
printSimpleLocation(StringRef Filename,const DILineInfo & Info)1325f57793cSAlex Orlov void LLVMPrinter::printSimpleLocation(StringRef Filename,
1335f57793cSAlex Orlov const DILineInfo &Info) {
1345f57793cSAlex Orlov OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n';
135752385b1SAlex Orlov printContext(
136752385b1SAlex Orlov SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
1375f57793cSAlex Orlov }
1385f57793cSAlex Orlov
printSimpleLocation(StringRef Filename,const DILineInfo & Info)1395f57793cSAlex Orlov void GNUPrinter::printSimpleLocation(StringRef Filename,
1405f57793cSAlex Orlov const DILineInfo &Info) {
1415f57793cSAlex Orlov OS << Filename << ':' << Info.Line;
1425f57793cSAlex Orlov if (Info.Discriminator)
1435f57793cSAlex Orlov OS << " (discriminator " << Info.Discriminator << ')';
1445f57793cSAlex Orlov OS << '\n';
145752385b1SAlex Orlov printContext(
146752385b1SAlex Orlov SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source));
1475f57793cSAlex Orlov }
1485f57793cSAlex Orlov
printVerbose(StringRef Filename,const DILineInfo & Info)1495f57793cSAlex Orlov void PlainPrinterBase::printVerbose(StringRef Filename,
1505f57793cSAlex Orlov const DILineInfo &Info) {
1515f57793cSAlex Orlov OS << " Filename: " << Filename << '\n';
1525f57793cSAlex Orlov if (Info.StartLine) {
1535f57793cSAlex Orlov OS << " Function start filename: " << Info.StartFileName << '\n';
1545f57793cSAlex Orlov OS << " Function start line: " << Info.StartLine << '\n';
1555f57793cSAlex Orlov }
1564fedb3a6SAlex Orlov printStartAddress(Info);
1575f57793cSAlex Orlov OS << " Line: " << Info.Line << '\n';
1585f57793cSAlex Orlov OS << " Column: " << Info.Column << '\n';
1595f57793cSAlex Orlov if (Info.Discriminator)
1605f57793cSAlex Orlov OS << " Discriminator: " << Info.Discriminator << '\n';
1615f57793cSAlex Orlov }
1625f57793cSAlex Orlov
printStartAddress(const DILineInfo & Info)1634fedb3a6SAlex Orlov void LLVMPrinter::printStartAddress(const DILineInfo &Info) {
1644fedb3a6SAlex Orlov if (Info.StartAddress) {
1654fedb3a6SAlex Orlov OS << " Function start address: 0x";
1664fedb3a6SAlex Orlov OS.write_hex(*Info.StartAddress);
1674fedb3a6SAlex Orlov OS << '\n';
1684fedb3a6SAlex Orlov }
1694fedb3a6SAlex Orlov }
1704fedb3a6SAlex Orlov
printFooter()1715f57793cSAlex Orlov void LLVMPrinter::printFooter() { OS << '\n'; }
1725f57793cSAlex Orlov
print(const DILineInfo & Info,bool Inlined)1735f57793cSAlex Orlov void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) {
1745f57793cSAlex Orlov printFunctionName(Info.FunctionName, Inlined);
1755f57793cSAlex Orlov StringRef Filename = Info.FileName;
1769abf668cSMichael Pozulp if (Filename == DILineInfo::BadString)
1779abf668cSMichael Pozulp Filename = DILineInfo::Addr2LineBadString;
1785f57793cSAlex Orlov if (Config.Verbose)
1795f57793cSAlex Orlov printVerbose(Filename, Info);
1805f57793cSAlex Orlov else
1815f57793cSAlex Orlov printSimpleLocation(Filename, Info);
182bdce12a0SHemant Kulkarni }
183bdce12a0SHemant Kulkarni
print(const Request & Request,const DILineInfo & Info)1845f57793cSAlex Orlov void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) {
18505d1ae4eSAlex Orlov printHeader(*Request.Address);
18617dbc283SMike Aizatsky print(Info, false);
1875f57793cSAlex Orlov printFooter();
188d6aa8202SAlexey Samsonov }
189d6aa8202SAlexey Samsonov
print(const Request & Request,const DIInliningInfo & Info)1905f57793cSAlex Orlov void PlainPrinterBase::print(const Request &Request,
1915f57793cSAlex Orlov const DIInliningInfo &Info) {
19205d1ae4eSAlex Orlov printHeader(*Request.Address);
193d6aa8202SAlexey Samsonov uint32_t FramesNum = Info.getNumberOfFrames();
1945f57793cSAlex Orlov if (FramesNum == 0)
19517dbc283SMike Aizatsky print(DILineInfo(), false);
1965f57793cSAlex Orlov else
1975f57793cSAlex Orlov for (uint32_t I = 0; I < FramesNum; ++I)
1985f57793cSAlex Orlov print(Info.getFrame(I), I > 0);
1995f57793cSAlex Orlov printFooter();
200d6aa8202SAlexey Samsonov }
201d6aa8202SAlexey Samsonov
print(const Request & Request,const DIGlobal & Global)2025f57793cSAlex Orlov void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) {
20305d1ae4eSAlex Orlov printHeader(*Request.Address);
2045f57793cSAlex Orlov StringRef Name = Global.Name;
2059abf668cSMichael Pozulp if (Name == DILineInfo::BadString)
2069abf668cSMichael Pozulp Name = DILineInfo::Addr2LineBadString;
207d6aa8202SAlexey Samsonov OS << Name << "\n";
208d6aa8202SAlexey Samsonov OS << Global.Start << " " << Global.Size << "\n";
209*cead4eceSMitch Phillips if (Global.DeclFile.empty())
210*cead4eceSMitch Phillips OS << "??:?\n";
211*cead4eceSMitch Phillips else
212*cead4eceSMitch Phillips OS << Global.DeclFile << ":" << Global.DeclLine << "\n";
2135f57793cSAlex Orlov printFooter();
214d6aa8202SAlexey Samsonov }
215d6aa8202SAlexey Samsonov
print(const Request & Request,const std::vector<DILocal> & Locals)2165f57793cSAlex Orlov void PlainPrinterBase::print(const Request &Request,
2175f57793cSAlex Orlov const std::vector<DILocal> &Locals) {
21805d1ae4eSAlex Orlov printHeader(*Request.Address);
2195f57793cSAlex Orlov if (Locals.empty())
2205f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString << '\n';
2211c33d713SEvgenii Stepanov else
2225f57793cSAlex Orlov for (const DILocal &L : Locals) {
2235f57793cSAlex Orlov if (L.FunctionName.empty())
2245f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2255f57793cSAlex Orlov else
2265f57793cSAlex Orlov OS << L.FunctionName;
2275f57793cSAlex Orlov OS << '\n';
2281c33d713SEvgenii Stepanov
2295f57793cSAlex Orlov if (L.Name.empty())
2305f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2311c33d713SEvgenii Stepanov else
2325f57793cSAlex Orlov OS << L.Name;
2335f57793cSAlex Orlov OS << '\n';
2341c33d713SEvgenii Stepanov
2355f57793cSAlex Orlov if (L.DeclFile.empty())
2365f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2379c8282a9SPeter Collingbourne else
2385f57793cSAlex Orlov OS << L.DeclFile;
2391c33d713SEvgenii Stepanov
2405f57793cSAlex Orlov OS << ':' << L.DeclLine << '\n';
2411c33d713SEvgenii Stepanov
2425f57793cSAlex Orlov if (L.FrameOffset)
2435f57793cSAlex Orlov OS << *L.FrameOffset;
2449c8282a9SPeter Collingbourne else
2455f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2465f57793cSAlex Orlov OS << ' ';
2471c33d713SEvgenii Stepanov
2485f57793cSAlex Orlov if (L.Size)
2495f57793cSAlex Orlov OS << *L.Size;
2509c8282a9SPeter Collingbourne else
2515f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2525f57793cSAlex Orlov OS << ' ';
2535f57793cSAlex Orlov
2545f57793cSAlex Orlov if (L.TagOffset)
2555f57793cSAlex Orlov OS << *L.TagOffset;
2565f57793cSAlex Orlov else
2575f57793cSAlex Orlov OS << DILineInfo::Addr2LineBadString;
2585f57793cSAlex Orlov OS << '\n';
2595f57793cSAlex Orlov }
2605f57793cSAlex Orlov printFooter();
2615f57793cSAlex Orlov }
2625f57793cSAlex Orlov
printInvalidCommand(const Request & Request,StringRef Command)2635f57793cSAlex Orlov void PlainPrinterBase::printInvalidCommand(const Request &Request,
26405d1ae4eSAlex Orlov StringRef Command) {
26505d1ae4eSAlex Orlov OS << Command << '\n';
2665f57793cSAlex Orlov }
2675f57793cSAlex Orlov
printError(const Request & Request,const ErrorInfoBase & ErrorInfo,StringRef ErrorBanner)2685f57793cSAlex Orlov bool PlainPrinterBase::printError(const Request &Request,
2695f57793cSAlex Orlov const ErrorInfoBase &ErrorInfo,
2705f57793cSAlex Orlov StringRef ErrorBanner) {
2715f57793cSAlex Orlov ES << ErrorBanner;
2725f57793cSAlex Orlov ErrorInfo.log(ES);
2735f57793cSAlex Orlov ES << '\n';
2745f57793cSAlex Orlov // Print an empty struct too.
2755f57793cSAlex Orlov return true;
2769c8282a9SPeter Collingbourne }
2779c8282a9SPeter Collingbourne
toHex(uint64_t V)27805d1ae4eSAlex Orlov static std::string toHex(uint64_t V) {
27905d1ae4eSAlex Orlov return ("0x" + Twine::utohexstr(V)).str();
28005d1ae4eSAlex Orlov }
28105d1ae4eSAlex Orlov
toJSON(const Request & Request,StringRef ErrorMsg="")28205d1ae4eSAlex Orlov static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") {
28305d1ae4eSAlex Orlov json::Object Json({{"ModuleName", Request.ModuleName.str()}});
28405d1ae4eSAlex Orlov if (Request.Address)
28505d1ae4eSAlex Orlov Json["Address"] = toHex(*Request.Address);
28605d1ae4eSAlex Orlov if (!ErrorMsg.empty())
28705d1ae4eSAlex Orlov Json["Error"] = json::Object({{"Message", ErrorMsg.str()}});
28805d1ae4eSAlex Orlov return Json;
28905d1ae4eSAlex Orlov }
29005d1ae4eSAlex Orlov
print(const Request & Request,const DILineInfo & Info)29105d1ae4eSAlex Orlov void JSONPrinter::print(const Request &Request, const DILineInfo &Info) {
29205d1ae4eSAlex Orlov DIInliningInfo InliningInfo;
29305d1ae4eSAlex Orlov InliningInfo.addFrame(Info);
29405d1ae4eSAlex Orlov print(Request, InliningInfo);
29505d1ae4eSAlex Orlov }
29605d1ae4eSAlex Orlov
print(const Request & Request,const DIInliningInfo & Info)29705d1ae4eSAlex Orlov void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) {
29805d1ae4eSAlex Orlov json::Array Array;
29905d1ae4eSAlex Orlov for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) {
30005d1ae4eSAlex Orlov const DILineInfo &LineInfo = Info.getFrame(I);
301752385b1SAlex Orlov json::Object Object(
30205d1ae4eSAlex Orlov {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString
30305d1ae4eSAlex Orlov ? LineInfo.FunctionName
30405d1ae4eSAlex Orlov : ""},
30505d1ae4eSAlex Orlov {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString
30605d1ae4eSAlex Orlov ? LineInfo.StartFileName
30705d1ae4eSAlex Orlov : ""},
30805d1ae4eSAlex Orlov {"StartLine", LineInfo.StartLine},
3094fedb3a6SAlex Orlov {"StartAddress",
3104fedb3a6SAlex Orlov LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""},
31105d1ae4eSAlex Orlov {"FileName",
31205d1ae4eSAlex Orlov LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""},
31305d1ae4eSAlex Orlov {"Line", LineInfo.Line},
31405d1ae4eSAlex Orlov {"Column", LineInfo.Column},
315752385b1SAlex Orlov {"Discriminator", LineInfo.Discriminator}});
316752385b1SAlex Orlov SourceCode SourceCode(LineInfo.FileName, LineInfo.Line,
317752385b1SAlex Orlov Config.SourceContextLines, LineInfo.Source);
318752385b1SAlex Orlov std::string FormattedSource;
319752385b1SAlex Orlov raw_string_ostream Stream(FormattedSource);
320752385b1SAlex Orlov SourceCode.format(Stream);
321752385b1SAlex Orlov if (!FormattedSource.empty())
322752385b1SAlex Orlov Object["Source"] = std::move(FormattedSource);
323752385b1SAlex Orlov Array.push_back(std::move(Object));
32405d1ae4eSAlex Orlov }
32505d1ae4eSAlex Orlov json::Object Json = toJSON(Request);
32605d1ae4eSAlex Orlov Json["Symbol"] = std::move(Array);
32705d1ae4eSAlex Orlov if (ObjectList)
32805d1ae4eSAlex Orlov ObjectList->push_back(std::move(Json));
32905d1ae4eSAlex Orlov else
33005d1ae4eSAlex Orlov printJSON(std::move(Json));
33105d1ae4eSAlex Orlov }
33205d1ae4eSAlex Orlov
print(const Request & Request,const DIGlobal & Global)33305d1ae4eSAlex Orlov void JSONPrinter::print(const Request &Request, const DIGlobal &Global) {
33405d1ae4eSAlex Orlov json::Object Data(
33505d1ae4eSAlex Orlov {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""},
33605d1ae4eSAlex Orlov {"Start", toHex(Global.Start)},
33705d1ae4eSAlex Orlov {"Size", toHex(Global.Size)}});
33805d1ae4eSAlex Orlov json::Object Json = toJSON(Request);
33905d1ae4eSAlex Orlov Json["Data"] = std::move(Data);
34005d1ae4eSAlex Orlov if (ObjectList)
34105d1ae4eSAlex Orlov ObjectList->push_back(std::move(Json));
34205d1ae4eSAlex Orlov else
34305d1ae4eSAlex Orlov printJSON(std::move(Json));
34405d1ae4eSAlex Orlov }
34505d1ae4eSAlex Orlov
print(const Request & Request,const std::vector<DILocal> & Locals)34605d1ae4eSAlex Orlov void JSONPrinter::print(const Request &Request,
34705d1ae4eSAlex Orlov const std::vector<DILocal> &Locals) {
34805d1ae4eSAlex Orlov json::Array Frame;
34905d1ae4eSAlex Orlov for (const DILocal &Local : Locals) {
35005d1ae4eSAlex Orlov json::Object FrameObject(
35105d1ae4eSAlex Orlov {{"FunctionName", Local.FunctionName},
35205d1ae4eSAlex Orlov {"Name", Local.Name},
35305d1ae4eSAlex Orlov {"DeclFile", Local.DeclFile},
35405d1ae4eSAlex Orlov {"DeclLine", int64_t(Local.DeclLine)},
35505d1ae4eSAlex Orlov {"Size", Local.Size ? toHex(*Local.Size) : ""},
35605d1ae4eSAlex Orlov {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}});
35705d1ae4eSAlex Orlov if (Local.FrameOffset)
35805d1ae4eSAlex Orlov FrameObject["FrameOffset"] = *Local.FrameOffset;
35905d1ae4eSAlex Orlov Frame.push_back(std::move(FrameObject));
36005d1ae4eSAlex Orlov }
36105d1ae4eSAlex Orlov json::Object Json = toJSON(Request);
36205d1ae4eSAlex Orlov Json["Frame"] = std::move(Frame);
36305d1ae4eSAlex Orlov if (ObjectList)
36405d1ae4eSAlex Orlov ObjectList->push_back(std::move(Json));
36505d1ae4eSAlex Orlov else
36605d1ae4eSAlex Orlov printJSON(std::move(Json));
36705d1ae4eSAlex Orlov }
36805d1ae4eSAlex Orlov
printInvalidCommand(const Request & Request,StringRef Command)36905d1ae4eSAlex Orlov void JSONPrinter::printInvalidCommand(const Request &Request,
37005d1ae4eSAlex Orlov StringRef Command) {
37105d1ae4eSAlex Orlov printError(Request,
37205d1ae4eSAlex Orlov StringError("unable to parse arguments: " + Command,
37305d1ae4eSAlex Orlov std::make_error_code(std::errc::invalid_argument)),
37405d1ae4eSAlex Orlov "");
37505d1ae4eSAlex Orlov }
37605d1ae4eSAlex Orlov
printError(const Request & Request,const ErrorInfoBase & ErrorInfo,StringRef ErrorBanner)37705d1ae4eSAlex Orlov bool JSONPrinter::printError(const Request &Request,
37805d1ae4eSAlex Orlov const ErrorInfoBase &ErrorInfo,
37905d1ae4eSAlex Orlov StringRef ErrorBanner) {
38005d1ae4eSAlex Orlov json::Object Json = toJSON(Request, ErrorInfo.message());
38105d1ae4eSAlex Orlov if (ObjectList)
38205d1ae4eSAlex Orlov ObjectList->push_back(std::move(Json));
38305d1ae4eSAlex Orlov else
38405d1ae4eSAlex Orlov printJSON(std::move(Json));
38505d1ae4eSAlex Orlov return false;
38605d1ae4eSAlex Orlov }
38705d1ae4eSAlex Orlov
listBegin()38805d1ae4eSAlex Orlov void JSONPrinter::listBegin() {
38905d1ae4eSAlex Orlov assert(!ObjectList);
39005d1ae4eSAlex Orlov ObjectList = std::make_unique<json::Array>();
39105d1ae4eSAlex Orlov }
39205d1ae4eSAlex Orlov
listEnd()39305d1ae4eSAlex Orlov void JSONPrinter::listEnd() {
39405d1ae4eSAlex Orlov assert(ObjectList);
39505d1ae4eSAlex Orlov printJSON(std::move(*ObjectList));
39685a96d82SVitaly Buka ObjectList.reset();
39705d1ae4eSAlex Orlov }
39805d1ae4eSAlex Orlov
399417d4c50SEugene Zelenko } // end namespace symbolize
400417d4c50SEugene Zelenko } // end namespace llvm
401