llvm-dis.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. //===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This utility may be invoked in the following manner:
  10. // llvm-dis [options] - Read LLVM bitcode from stdin, write asm to stdout
  11. // llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm
  12. // to the x.ll file.
  13. // Options:
  14. // --help - Output information about command line switches
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #include "llvm/Bitcode/BitcodeReader.h"
  18. #include "llvm/IR/AssemblyAnnotationWriter.h"
  19. #include "llvm/IR/DebugInfo.h"
  20. #include "llvm/IR/DiagnosticInfo.h"
  21. #include "llvm/IR/DiagnosticPrinter.h"
  22. #include "llvm/IR/IntrinsicInst.h"
  23. #include "llvm/IR/LLVMContext.h"
  24. #include "llvm/IR/Module.h"
  25. #include "llvm/IR/ModuleSummaryIndex.h"
  26. #include "llvm/IR/Type.h"
  27. #include "llvm/Support/CommandLine.h"
  28. #include "llvm/Support/Error.h"
  29. #include "llvm/Support/FileSystem.h"
  30. #include "llvm/Support/FormattedStream.h"
  31. #include "llvm/Support/InitLLVM.h"
  32. #include "llvm/Support/MemoryBuffer.h"
  33. #include "llvm/Support/ToolOutputFile.h"
  34. #include "llvm/Support/WithColor.h"
  35. #include <system_error>
  36. using namespace llvm;
  37. static cl::OptionCategory DisCategory("Disassembler Options");
  38. static cl::list<std::string> InputFilenames(cl::Positional,
  39. cl::desc("[input bitcode]..."),
  40. cl::cat(DisCategory));
  41. static cl::opt<std::string> OutputFilename("o",
  42. cl::desc("Override output filename"),
  43. cl::value_desc("filename"),
  44. cl::cat(DisCategory));
  45. static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"),
  46. cl::cat(DisCategory));
  47. static cl::opt<bool> DontPrint("disable-output",
  48. cl::desc("Don't output the .ll file"),
  49. cl::Hidden, cl::cat(DisCategory));
  50. static cl::opt<bool>
  51. SetImporting("set-importing",
  52. cl::desc("Set lazy loading to pretend to import a module"),
  53. cl::Hidden, cl::cat(DisCategory));
  54. static cl::opt<bool>
  55. ShowAnnotations("show-annotations",
  56. cl::desc("Add informational comments to the .ll file"),
  57. cl::cat(DisCategory));
  58. static cl::opt<bool> PreserveAssemblyUseListOrder(
  59. "preserve-ll-uselistorder",
  60. cl::desc("Preserve use-list order when writing LLVM assembly."),
  61. cl::init(false), cl::Hidden, cl::cat(DisCategory));
  62. static cl::opt<bool>
  63. MaterializeMetadata("materialize-metadata",
  64. cl::desc("Load module without materializing metadata, "
  65. "then materialize only the metadata"),
  66. cl::cat(DisCategory));
  67. static cl::opt<bool> PrintThinLTOIndexOnly(
  68. "print-thinlto-index-only",
  69. cl::desc("Only read thinlto index and print the index as LLVM assembly."),
  70. cl::init(false), cl::Hidden, cl::cat(DisCategory));
  71. namespace {
  72. static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
  73. OS << DL.getLine() << ":" << DL.getCol();
  74. if (DILocation *IDL = DL.getInlinedAt()) {
  75. OS << "@";
  76. printDebugLoc(IDL, OS);
  77. }
  78. }
  79. class CommentWriter : public AssemblyAnnotationWriter {
  80. public:
  81. void emitFunctionAnnot(const Function *F,
  82. formatted_raw_ostream &OS) override {
  83. OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses
  84. OS << '\n';
  85. }
  86. void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {
  87. bool Padded = false;
  88. if (!V.getType()->isVoidTy()) {
  89. OS.PadToColumn(50);
  90. Padded = true;
  91. // Output # uses and type
  92. OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";
  93. }
  94. if (const Instruction *I = dyn_cast<Instruction>(&V)) {
  95. if (const DebugLoc &DL = I->getDebugLoc()) {
  96. if (!Padded) {
  97. OS.PadToColumn(50);
  98. Padded = true;
  99. OS << ";";
  100. }
  101. OS << " [debug line = ";
  102. printDebugLoc(DL,OS);
  103. OS << "]";
  104. }
  105. if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
  106. if (!Padded) {
  107. OS.PadToColumn(50);
  108. OS << ";";
  109. }
  110. OS << " [debug variable = " << DDI->getVariable()->getName() << "]";
  111. }
  112. else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
  113. if (!Padded) {
  114. OS.PadToColumn(50);
  115. OS << ";";
  116. }
  117. OS << " [debug variable = " << DVI->getVariable()->getName() << "]";
  118. }
  119. }
  120. }
  121. };
  122. struct LLVMDisDiagnosticHandler : public DiagnosticHandler {
  123. char *Prefix;
  124. LLVMDisDiagnosticHandler(char *PrefixPtr) : Prefix(PrefixPtr) {}
  125. bool handleDiagnostics(const DiagnosticInfo &DI) override {
  126. raw_ostream &OS = errs();
  127. OS << Prefix << ": ";
  128. switch (DI.getSeverity()) {
  129. case DS_Error: WithColor::error(OS); break;
  130. case DS_Warning: WithColor::warning(OS); break;
  131. case DS_Remark: OS << "remark: "; break;
  132. case DS_Note: WithColor::note(OS); break;
  133. }
  134. DiagnosticPrinterRawOStream DP(OS);
  135. DI.print(DP);
  136. OS << '\n';
  137. if (DI.getSeverity() == DS_Error)
  138. exit(1);
  139. return true;
  140. }
  141. };
  142. } // end anon namespace
  143. static ExitOnError ExitOnErr;
  144. int main(int argc, char **argv) {
  145. InitLLVM X(argc, argv);
  146. ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");
  147. cl::HideUnrelatedOptions({&DisCategory, &getColorCategory()});
  148. cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
  149. LLVMContext Context;
  150. Context.setDiagnosticHandler(
  151. std::make_unique<LLVMDisDiagnosticHandler>(argv[0]));
  152. if (InputFilenames.size() < 1) {
  153. InputFilenames.push_back("-");
  154. } else if (InputFilenames.size() > 1 && !OutputFilename.empty()) {
  155. errs()
  156. << "error: output file name cannot be set for multiple input files\n";
  157. return 1;
  158. }
  159. for (std::string InputFilename : InputFilenames) {
  160. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
  161. MemoryBuffer::getFileOrSTDIN(InputFilename);
  162. if (std::error_code EC = BufferOrErr.getError()) {
  163. WithColor::error() << InputFilename << ": " << EC.message() << '\n';
  164. return 1;
  165. }
  166. std::unique_ptr<MemoryBuffer> MB = std::move(BufferOrErr.get());
  167. BitcodeFileContents IF = ExitOnErr(llvm::getBitcodeFileContents(*MB));
  168. const size_t N = IF.Mods.size();
  169. if (OutputFilename == "-" && N > 1)
  170. errs() << "only single module bitcode files can be written to stdout\n";
  171. for (size_t I = 0; I < N; ++I) {
  172. BitcodeModule MB = IF.Mods[I];
  173. std::unique_ptr<Module> M;
  174. if (!PrintThinLTOIndexOnly) {
  175. M = ExitOnErr(
  176. MB.getLazyModule(Context, MaterializeMetadata, SetImporting));
  177. if (MaterializeMetadata)
  178. ExitOnErr(M->materializeMetadata());
  179. else
  180. ExitOnErr(M->materializeAll());
  181. }
  182. BitcodeLTOInfo LTOInfo = ExitOnErr(MB.getLTOInfo());
  183. std::unique_ptr<ModuleSummaryIndex> Index;
  184. if (LTOInfo.HasSummary)
  185. Index = ExitOnErr(MB.getSummary());
  186. std::string FinalFilename(OutputFilename);
  187. // Just use stdout. We won't actually print anything on it.
  188. if (DontPrint)
  189. FinalFilename = "-";
  190. if (FinalFilename.empty()) { // Unspecified output, infer it.
  191. if (InputFilename == "-") {
  192. FinalFilename = "-";
  193. } else {
  194. StringRef IFN = InputFilename;
  195. FinalFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
  196. if (N > 1)
  197. FinalFilename += std::string(".") + std::to_string(I);
  198. FinalFilename += ".ll";
  199. }
  200. } else {
  201. if (N > 1)
  202. FinalFilename += std::string(".") + std::to_string(I);
  203. }
  204. std::error_code EC;
  205. std::unique_ptr<ToolOutputFile> Out(
  206. new ToolOutputFile(FinalFilename, EC, sys::fs::OF_TextWithCRLF));
  207. if (EC) {
  208. errs() << EC.message() << '\n';
  209. return 1;
  210. }
  211. std::unique_ptr<AssemblyAnnotationWriter> Annotator;
  212. if (ShowAnnotations)
  213. Annotator.reset(new CommentWriter());
  214. // All that llvm-dis does is write the assembly to a file.
  215. if (!DontPrint) {
  216. if (M)
  217. M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);
  218. if (Index)
  219. Index->print(Out->os());
  220. }
  221. // Declare success.
  222. Out->keep();
  223. }
  224. }
  225. return 0;
  226. }