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/LineIterator.h" 200b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 210b57cec5SDimitry Andric #include "llvm/Support/Path.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 230b57cec5SDimitry Andric #include <algorithm> 240b57cec5SDimitry Andric #include <cmath> 250b57cec5SDimitry Andric #include <cstddef> 260b57cec5SDimitry Andric #include <cstdint> 270b57cec5SDimitry Andric #include <memory> 280b57cec5SDimitry Andric #include <string> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric namespace symbolize { 320b57cec5SDimitry Andric 33*fe6060f1SDimitry Andric class SourceCode { 34*fe6060f1SDimitry Andric std::unique_ptr<MemoryBuffer> MemBuf; 350b57cec5SDimitry Andric 36*fe6060f1SDimitry Andric const Optional<StringRef> load(StringRef FileName, 37*fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource) { 38*fe6060f1SDimitry Andric if (Lines <= 0) 39*fe6060f1SDimitry Andric return None; 40*fe6060f1SDimitry Andric 41*fe6060f1SDimitry Andric if (EmbeddedSource) 42*fe6060f1SDimitry Andric return EmbeddedSource; 43*fe6060f1SDimitry Andric else { 440b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = 450b57cec5SDimitry Andric MemoryBuffer::getFile(FileName); 460b57cec5SDimitry Andric if (!BufOrErr) 47*fe6060f1SDimitry Andric return None; 48*fe6060f1SDimitry Andric MemBuf = std::move(*BufOrErr); 49*fe6060f1SDimitry Andric return MemBuf->getBuffer(); 50*fe6060f1SDimitry Andric } 51*fe6060f1SDimitry Andric } 52*fe6060f1SDimitry Andric 53*fe6060f1SDimitry Andric const Optional<StringRef> pruneSource(const Optional<StringRef> &Source) { 54*fe6060f1SDimitry Andric if (!Source) 55*fe6060f1SDimitry Andric return None; 56*fe6060f1SDimitry Andric size_t FirstLinePos = StringRef::npos, Pos = 0; 57*fe6060f1SDimitry Andric for (int64_t L = 1; L <= LastLine; ++L, ++Pos) { 58*fe6060f1SDimitry Andric if (L == FirstLine) 59*fe6060f1SDimitry Andric FirstLinePos = Pos; 60*fe6060f1SDimitry Andric Pos = Source->find('\n', Pos); 61*fe6060f1SDimitry Andric if (Pos == StringRef::npos) 62*fe6060f1SDimitry Andric break; 63*fe6060f1SDimitry Andric } 64*fe6060f1SDimitry Andric if (FirstLinePos == StringRef::npos) 65*fe6060f1SDimitry Andric return None; 66*fe6060f1SDimitry Andric return Source->substr(FirstLinePos, (Pos == StringRef::npos) 67*fe6060f1SDimitry Andric ? StringRef::npos 68*fe6060f1SDimitry Andric : Pos - FirstLinePos); 69*fe6060f1SDimitry Andric } 70*fe6060f1SDimitry Andric 71*fe6060f1SDimitry Andric public: 72*fe6060f1SDimitry Andric const int64_t Line; 73*fe6060f1SDimitry Andric const int Lines; 74*fe6060f1SDimitry Andric const int64_t FirstLine; 75*fe6060f1SDimitry Andric const int64_t LastLine; 76*fe6060f1SDimitry Andric const Optional<StringRef> PrunedSource; 77*fe6060f1SDimitry Andric 78*fe6060f1SDimitry Andric SourceCode( 79*fe6060f1SDimitry Andric StringRef FileName, int64_t Line, int Lines, 80*fe6060f1SDimitry Andric const Optional<StringRef> &EmbeddedSource = Optional<StringRef>(None)) 81*fe6060f1SDimitry Andric : Line(Line), Lines(Lines), 82*fe6060f1SDimitry Andric FirstLine(std::max(static_cast<int64_t>(1), Line - Lines / 2)), 83*fe6060f1SDimitry Andric LastLine(FirstLine + Lines - 1), 84*fe6060f1SDimitry Andric PrunedSource(pruneSource(load(FileName, EmbeddedSource))) {} 85*fe6060f1SDimitry Andric 86*fe6060f1SDimitry Andric void format(raw_ostream &OS) { 87*fe6060f1SDimitry Andric if (!PrunedSource) 880b57cec5SDimitry Andric return; 890b57cec5SDimitry Andric size_t MaxLineNumberWidth = std::ceil(std::log10(LastLine)); 90*fe6060f1SDimitry Andric int64_t L = FirstLine; 91*fe6060f1SDimitry Andric for (size_t Pos = 0; Pos < PrunedSource->size(); ++L) { 92*fe6060f1SDimitry Andric size_t PosEnd = PrunedSource->find('\n', Pos); 93*fe6060f1SDimitry Andric StringRef String = PrunedSource->substr( 94*fe6060f1SDimitry Andric Pos, (PosEnd == StringRef::npos) ? StringRef::npos : (PosEnd - Pos)); 95*fe6060f1SDimitry Andric if (String.endswith("\r")) 96*fe6060f1SDimitry Andric String = String.drop_back(1); 970b57cec5SDimitry Andric OS << format_decimal(L, MaxLineNumberWidth); 980b57cec5SDimitry Andric if (L == Line) 990b57cec5SDimitry Andric OS << " >: "; 1000b57cec5SDimitry Andric else 1010b57cec5SDimitry Andric OS << " : "; 102*fe6060f1SDimitry Andric OS << String << '\n'; 103*fe6060f1SDimitry Andric if (PosEnd == StringRef::npos) 104*fe6060f1SDimitry Andric break; 105*fe6060f1SDimitry Andric Pos = PosEnd + 1; 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric } 108*fe6060f1SDimitry Andric }; 109*fe6060f1SDimitry Andric 110*fe6060f1SDimitry Andric void PlainPrinterBase::printHeader(uint64_t Address) { 111*fe6060f1SDimitry Andric if (Config.PrintAddress) { 112*fe6060f1SDimitry Andric OS << "0x"; 113*fe6060f1SDimitry Andric OS.write_hex(Address); 114*fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? ": " : "\n"; 115*fe6060f1SDimitry Andric OS << Delimiter; 116*fe6060f1SDimitry Andric } 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 119*fe6060f1SDimitry Andric // Prints source code around in the FileName the Line. 120*fe6060f1SDimitry Andric void PlainPrinterBase::printContext(SourceCode SourceCode) { 121*fe6060f1SDimitry Andric SourceCode.format(OS); 122*fe6060f1SDimitry Andric } 123*fe6060f1SDimitry Andric 124*fe6060f1SDimitry Andric void PlainPrinterBase::printFunctionName(StringRef FunctionName, bool Inlined) { 125*fe6060f1SDimitry Andric if (Config.PrintFunctions) { 1268bcb0991SDimitry Andric if (FunctionName == DILineInfo::BadString) 1278bcb0991SDimitry Andric FunctionName = DILineInfo::Addr2LineBadString; 128*fe6060f1SDimitry Andric StringRef Delimiter = Config.Pretty ? " at " : "\n"; 129*fe6060f1SDimitry Andric StringRef Prefix = (Config.Pretty && Inlined) ? " (inlined by) " : ""; 1300b57cec5SDimitry Andric OS << Prefix << FunctionName << Delimiter; 1310b57cec5SDimitry Andric } 132*fe6060f1SDimitry Andric } 133*fe6060f1SDimitry Andric 134*fe6060f1SDimitry Andric void LLVMPrinter::printSimpleLocation(StringRef Filename, 135*fe6060f1SDimitry Andric const DILineInfo &Info) { 136*fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line << ':' << Info.Column << '\n'; 137*fe6060f1SDimitry Andric printContext( 138*fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 139*fe6060f1SDimitry Andric } 140*fe6060f1SDimitry Andric 141*fe6060f1SDimitry Andric void GNUPrinter::printSimpleLocation(StringRef Filename, 142*fe6060f1SDimitry Andric const DILineInfo &Info) { 143*fe6060f1SDimitry Andric OS << Filename << ':' << Info.Line; 144*fe6060f1SDimitry Andric if (Info.Discriminator) 145*fe6060f1SDimitry Andric OS << " (discriminator " << Info.Discriminator << ')'; 146*fe6060f1SDimitry Andric OS << '\n'; 147*fe6060f1SDimitry Andric printContext( 148*fe6060f1SDimitry Andric SourceCode(Filename, Info.Line, Config.SourceContextLines, Info.Source)); 149*fe6060f1SDimitry Andric } 150*fe6060f1SDimitry Andric 151*fe6060f1SDimitry Andric void PlainPrinterBase::printVerbose(StringRef Filename, 152*fe6060f1SDimitry Andric const DILineInfo &Info) { 153*fe6060f1SDimitry Andric OS << " Filename: " << Filename << '\n'; 154*fe6060f1SDimitry Andric if (Info.StartLine) { 155*fe6060f1SDimitry Andric OS << " Function start filename: " << Info.StartFileName << '\n'; 156*fe6060f1SDimitry Andric OS << " Function start line: " << Info.StartLine << '\n'; 157*fe6060f1SDimitry Andric } 158*fe6060f1SDimitry Andric printStartAddress(Info); 159*fe6060f1SDimitry Andric OS << " Line: " << Info.Line << '\n'; 160*fe6060f1SDimitry Andric OS << " Column: " << Info.Column << '\n'; 161*fe6060f1SDimitry Andric if (Info.Discriminator) 162*fe6060f1SDimitry Andric OS << " Discriminator: " << Info.Discriminator << '\n'; 163*fe6060f1SDimitry Andric } 164*fe6060f1SDimitry Andric 165*fe6060f1SDimitry Andric void LLVMPrinter::printStartAddress(const DILineInfo &Info) { 166*fe6060f1SDimitry Andric if (Info.StartAddress) { 167*fe6060f1SDimitry Andric OS << " Function start address: 0x"; 168*fe6060f1SDimitry Andric OS.write_hex(*Info.StartAddress); 169*fe6060f1SDimitry Andric OS << '\n'; 170*fe6060f1SDimitry Andric } 171*fe6060f1SDimitry Andric } 172*fe6060f1SDimitry Andric 173*fe6060f1SDimitry Andric void LLVMPrinter::printFooter() { OS << '\n'; } 174*fe6060f1SDimitry Andric 175*fe6060f1SDimitry Andric void PlainPrinterBase::print(const DILineInfo &Info, bool Inlined) { 176*fe6060f1SDimitry Andric printFunctionName(Info.FunctionName, Inlined); 177*fe6060f1SDimitry Andric StringRef Filename = Info.FileName; 1788bcb0991SDimitry Andric if (Filename == DILineInfo::BadString) 1798bcb0991SDimitry Andric Filename = DILineInfo::Addr2LineBadString; 180*fe6060f1SDimitry Andric if (Config.Verbose) 181*fe6060f1SDimitry Andric printVerbose(Filename, Info); 182*fe6060f1SDimitry Andric else 183*fe6060f1SDimitry Andric printSimpleLocation(Filename, Info); 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 186*fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DILineInfo &Info) { 187*fe6060f1SDimitry Andric printHeader(*Request.Address); 1880b57cec5SDimitry Andric print(Info, false); 189*fe6060f1SDimitry Andric printFooter(); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric 192*fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 193*fe6060f1SDimitry Andric const DIInliningInfo &Info) { 194*fe6060f1SDimitry Andric printHeader(*Request.Address); 1950b57cec5SDimitry Andric uint32_t FramesNum = Info.getNumberOfFrames(); 196*fe6060f1SDimitry Andric if (FramesNum == 0) 1970b57cec5SDimitry Andric print(DILineInfo(), false); 198*fe6060f1SDimitry Andric else 199*fe6060f1SDimitry Andric for (uint32_t I = 0; I < FramesNum; ++I) 200*fe6060f1SDimitry Andric print(Info.getFrame(I), I > 0); 201*fe6060f1SDimitry Andric printFooter(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 204*fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { 205*fe6060f1SDimitry Andric printHeader(*Request.Address); 206*fe6060f1SDimitry Andric StringRef Name = Global.Name; 2078bcb0991SDimitry Andric if (Name == DILineInfo::BadString) 2088bcb0991SDimitry Andric Name = DILineInfo::Addr2LineBadString; 2090b57cec5SDimitry Andric OS << Name << "\n"; 2100b57cec5SDimitry Andric OS << Global.Start << " " << Global.Size << "\n"; 211*fe6060f1SDimitry Andric printFooter(); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 214*fe6060f1SDimitry Andric void PlainPrinterBase::print(const Request &Request, 215*fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 216*fe6060f1SDimitry Andric printHeader(*Request.Address); 217*fe6060f1SDimitry Andric if (Locals.empty()) 218*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString << '\n'; 219480093f4SDimitry Andric else 220*fe6060f1SDimitry Andric for (const DILocal &L : Locals) { 221*fe6060f1SDimitry Andric if (L.FunctionName.empty()) 222*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 223480093f4SDimitry Andric else 224*fe6060f1SDimitry Andric OS << L.FunctionName; 225*fe6060f1SDimitry Andric OS << '\n'; 226480093f4SDimitry Andric 227*fe6060f1SDimitry Andric if (L.Name.empty()) 228*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 2290b57cec5SDimitry Andric else 230*fe6060f1SDimitry Andric OS << L.Name; 231*fe6060f1SDimitry Andric OS << '\n'; 232480093f4SDimitry Andric 233*fe6060f1SDimitry Andric if (L.DeclFile.empty()) 234*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 235*fe6060f1SDimitry Andric else 236*fe6060f1SDimitry Andric OS << L.DeclFile; 237*fe6060f1SDimitry Andric 238*fe6060f1SDimitry Andric OS << ':' << L.DeclLine << '\n'; 239*fe6060f1SDimitry Andric 240*fe6060f1SDimitry Andric if (L.FrameOffset) 241*fe6060f1SDimitry Andric OS << *L.FrameOffset; 242*fe6060f1SDimitry Andric else 243*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 244*fe6060f1SDimitry Andric OS << ' '; 245*fe6060f1SDimitry Andric 246*fe6060f1SDimitry Andric if (L.Size) 247*fe6060f1SDimitry Andric OS << *L.Size; 248*fe6060f1SDimitry Andric else 249*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 250*fe6060f1SDimitry Andric OS << ' '; 251*fe6060f1SDimitry Andric 252*fe6060f1SDimitry Andric if (L.TagOffset) 253*fe6060f1SDimitry Andric OS << *L.TagOffset; 254*fe6060f1SDimitry Andric else 255*fe6060f1SDimitry Andric OS << DILineInfo::Addr2LineBadString; 256*fe6060f1SDimitry Andric OS << '\n'; 257*fe6060f1SDimitry Andric } 258*fe6060f1SDimitry Andric printFooter(); 259*fe6060f1SDimitry Andric } 260*fe6060f1SDimitry Andric 261*fe6060f1SDimitry Andric void PlainPrinterBase::printInvalidCommand(const Request &Request, 262*fe6060f1SDimitry Andric StringRef Command) { 263*fe6060f1SDimitry Andric OS << Command << '\n'; 264*fe6060f1SDimitry Andric } 265*fe6060f1SDimitry Andric 266*fe6060f1SDimitry Andric bool PlainPrinterBase::printError(const Request &Request, 267*fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 268*fe6060f1SDimitry Andric StringRef ErrorBanner) { 269*fe6060f1SDimitry Andric ES << ErrorBanner; 270*fe6060f1SDimitry Andric ErrorInfo.log(ES); 271*fe6060f1SDimitry Andric ES << '\n'; 272*fe6060f1SDimitry Andric // Print an empty struct too. 273*fe6060f1SDimitry Andric return true; 274*fe6060f1SDimitry Andric } 275*fe6060f1SDimitry Andric 276*fe6060f1SDimitry Andric static std::string toHex(uint64_t V) { 277*fe6060f1SDimitry Andric return ("0x" + Twine::utohexstr(V)).str(); 278*fe6060f1SDimitry Andric } 279*fe6060f1SDimitry Andric 280*fe6060f1SDimitry Andric static json::Object toJSON(const Request &Request, StringRef ErrorMsg = "") { 281*fe6060f1SDimitry Andric json::Object Json({{"ModuleName", Request.ModuleName.str()}}); 282*fe6060f1SDimitry Andric if (Request.Address) 283*fe6060f1SDimitry Andric Json["Address"] = toHex(*Request.Address); 284*fe6060f1SDimitry Andric if (!ErrorMsg.empty()) 285*fe6060f1SDimitry Andric Json["Error"] = json::Object({{"Message", ErrorMsg.str()}}); 286*fe6060f1SDimitry Andric return Json; 287*fe6060f1SDimitry Andric } 288*fe6060f1SDimitry Andric 289*fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DILineInfo &Info) { 290*fe6060f1SDimitry Andric DIInliningInfo InliningInfo; 291*fe6060f1SDimitry Andric InliningInfo.addFrame(Info); 292*fe6060f1SDimitry Andric print(Request, InliningInfo); 293*fe6060f1SDimitry Andric } 294*fe6060f1SDimitry Andric 295*fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIInliningInfo &Info) { 296*fe6060f1SDimitry Andric json::Array Array; 297*fe6060f1SDimitry Andric for (uint32_t I = 0, N = Info.getNumberOfFrames(); I < N; ++I) { 298*fe6060f1SDimitry Andric const DILineInfo &LineInfo = Info.getFrame(I); 299*fe6060f1SDimitry Andric json::Object Object( 300*fe6060f1SDimitry Andric {{"FunctionName", LineInfo.FunctionName != DILineInfo::BadString 301*fe6060f1SDimitry Andric ? LineInfo.FunctionName 302*fe6060f1SDimitry Andric : ""}, 303*fe6060f1SDimitry Andric {"StartFileName", LineInfo.StartFileName != DILineInfo::BadString 304*fe6060f1SDimitry Andric ? LineInfo.StartFileName 305*fe6060f1SDimitry Andric : ""}, 306*fe6060f1SDimitry Andric {"StartLine", LineInfo.StartLine}, 307*fe6060f1SDimitry Andric {"StartAddress", 308*fe6060f1SDimitry Andric LineInfo.StartAddress ? toHex(*LineInfo.StartAddress) : ""}, 309*fe6060f1SDimitry Andric {"FileName", 310*fe6060f1SDimitry Andric LineInfo.FileName != DILineInfo::BadString ? LineInfo.FileName : ""}, 311*fe6060f1SDimitry Andric {"Line", LineInfo.Line}, 312*fe6060f1SDimitry Andric {"Column", LineInfo.Column}, 313*fe6060f1SDimitry Andric {"Discriminator", LineInfo.Discriminator}}); 314*fe6060f1SDimitry Andric SourceCode SourceCode(LineInfo.FileName, LineInfo.Line, 315*fe6060f1SDimitry Andric Config.SourceContextLines, LineInfo.Source); 316*fe6060f1SDimitry Andric std::string FormattedSource; 317*fe6060f1SDimitry Andric raw_string_ostream Stream(FormattedSource); 318*fe6060f1SDimitry Andric SourceCode.format(Stream); 319*fe6060f1SDimitry Andric if (!FormattedSource.empty()) 320*fe6060f1SDimitry Andric Object["Source"] = std::move(FormattedSource); 321*fe6060f1SDimitry Andric Array.push_back(std::move(Object)); 322*fe6060f1SDimitry Andric } 323*fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 324*fe6060f1SDimitry Andric Json["Symbol"] = std::move(Array); 325*fe6060f1SDimitry Andric if (ObjectList) 326*fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 327*fe6060f1SDimitry Andric else 328*fe6060f1SDimitry Andric printJSON(std::move(Json)); 329*fe6060f1SDimitry Andric } 330*fe6060f1SDimitry Andric 331*fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, const DIGlobal &Global) { 332*fe6060f1SDimitry Andric json::Object Data( 333*fe6060f1SDimitry Andric {{"Name", Global.Name != DILineInfo::BadString ? Global.Name : ""}, 334*fe6060f1SDimitry Andric {"Start", toHex(Global.Start)}, 335*fe6060f1SDimitry Andric {"Size", toHex(Global.Size)}}); 336*fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 337*fe6060f1SDimitry Andric Json["Data"] = std::move(Data); 338*fe6060f1SDimitry Andric if (ObjectList) 339*fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 340*fe6060f1SDimitry Andric else 341*fe6060f1SDimitry Andric printJSON(std::move(Json)); 342*fe6060f1SDimitry Andric } 343*fe6060f1SDimitry Andric 344*fe6060f1SDimitry Andric void JSONPrinter::print(const Request &Request, 345*fe6060f1SDimitry Andric const std::vector<DILocal> &Locals) { 346*fe6060f1SDimitry Andric json::Array Frame; 347*fe6060f1SDimitry Andric for (const DILocal &Local : Locals) { 348*fe6060f1SDimitry Andric json::Object FrameObject( 349*fe6060f1SDimitry Andric {{"FunctionName", Local.FunctionName}, 350*fe6060f1SDimitry Andric {"Name", Local.Name}, 351*fe6060f1SDimitry Andric {"DeclFile", Local.DeclFile}, 352*fe6060f1SDimitry Andric {"DeclLine", int64_t(Local.DeclLine)}, 353*fe6060f1SDimitry Andric {"Size", Local.Size ? toHex(*Local.Size) : ""}, 354*fe6060f1SDimitry Andric {"TagOffset", Local.TagOffset ? toHex(*Local.TagOffset) : ""}}); 3550b57cec5SDimitry Andric if (Local.FrameOffset) 356*fe6060f1SDimitry Andric FrameObject["FrameOffset"] = *Local.FrameOffset; 357*fe6060f1SDimitry Andric Frame.push_back(std::move(FrameObject)); 358*fe6060f1SDimitry Andric } 359*fe6060f1SDimitry Andric json::Object Json = toJSON(Request); 360*fe6060f1SDimitry Andric Json["Frame"] = std::move(Frame); 361*fe6060f1SDimitry Andric if (ObjectList) 362*fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3630b57cec5SDimitry Andric else 364*fe6060f1SDimitry Andric printJSON(std::move(Json)); 365*fe6060f1SDimitry Andric } 366480093f4SDimitry Andric 367*fe6060f1SDimitry Andric void JSONPrinter::printInvalidCommand(const Request &Request, 368*fe6060f1SDimitry Andric StringRef Command) { 369*fe6060f1SDimitry Andric printError(Request, 370*fe6060f1SDimitry Andric StringError("unable to parse arguments: " + Command, 371*fe6060f1SDimitry Andric std::make_error_code(std::errc::invalid_argument)), 372*fe6060f1SDimitry Andric ""); 373*fe6060f1SDimitry Andric } 374480093f4SDimitry Andric 375*fe6060f1SDimitry Andric bool JSONPrinter::printError(const Request &Request, 376*fe6060f1SDimitry Andric const ErrorInfoBase &ErrorInfo, 377*fe6060f1SDimitry Andric StringRef ErrorBanner) { 378*fe6060f1SDimitry Andric json::Object Json = toJSON(Request, ErrorInfo.message()); 379*fe6060f1SDimitry Andric if (ObjectList) 380*fe6060f1SDimitry Andric ObjectList->push_back(std::move(Json)); 3810b57cec5SDimitry Andric else 382*fe6060f1SDimitry Andric printJSON(std::move(Json)); 383*fe6060f1SDimitry Andric return false; 384*fe6060f1SDimitry Andric } 385*fe6060f1SDimitry Andric 386*fe6060f1SDimitry Andric void JSONPrinter::listBegin() { 387*fe6060f1SDimitry Andric assert(!ObjectList); 388*fe6060f1SDimitry Andric ObjectList = std::make_unique<json::Array>(); 389*fe6060f1SDimitry Andric } 390*fe6060f1SDimitry Andric 391*fe6060f1SDimitry Andric void JSONPrinter::listEnd() { 392*fe6060f1SDimitry Andric assert(ObjectList); 393*fe6060f1SDimitry Andric printJSON(std::move(*ObjectList)); 394*fe6060f1SDimitry Andric ObjectList.reset(); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric } // end namespace symbolize 3980b57cec5SDimitry Andric } // end namespace llvm 399