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> 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 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 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 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 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. 118fe6060f1SDimitry Andric void PlainPrinterBase::printContext(SourceCode SourceCode) { 119fe6060f1SDimitry Andric SourceCode.format(OS); 120fe6060f1SDimitry Andric } 121fe6060f1SDimitry Andric 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 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 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 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 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 171fe6060f1SDimitry Andric void LLVMPrinter::printFooter() { OS << '\n'; } 172fe6060f1SDimitry Andric 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 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 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 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 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 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 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 281fe6060f1SDimitry Andric static std::string toHex(uint64_t V) { 282fe6060f1SDimitry Andric return ("0x" + Twine::utohexstr(V)).str(); 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric 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 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 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 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 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 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 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 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 401fe6060f1SDimitry Andric void JSONPrinter::listBegin() { 402fe6060f1SDimitry Andric assert(!ObjectList); 403fe6060f1SDimitry Andric ObjectList = std::make_unique<json::Array>(); 404fe6060f1SDimitry Andric } 405fe6060f1SDimitry Andric 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