Path: blob/main/contrib/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
35231 views
//===-- llvm-dis.cpp - The low-level LLVM disassembler --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This utility may be invoked in the following manner:9// llvm-dis [options] - Read LLVM bitcode from stdin, write asm to stdout10// llvm-dis [options] x.bc - Read LLVM bitcode from the x.bc file, write asm11// to the x.ll file.12// Options:13// --help - Output information about command line switches14//15//===----------------------------------------------------------------------===//1617#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>36using namespace llvm;3738static cl::OptionCategory DisCategory("Disassembler Options");3940static cl::list<std::string> InputFilenames(cl::Positional,41cl::desc("[input bitcode]..."),42cl::cat(DisCategory));4344static cl::opt<std::string> OutputFilename("o",45cl::desc("Override output filename"),46cl::value_desc("filename"),47cl::cat(DisCategory));4849static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"),50cl::cat(DisCategory));5152static cl::opt<bool> DontPrint("disable-output",53cl::desc("Don't output the .ll file"),54cl::Hidden, cl::cat(DisCategory));5556static cl::opt<bool>57SetImporting("set-importing",58cl::desc("Set lazy loading to pretend to import a module"),59cl::Hidden, cl::cat(DisCategory));6061static cl::opt<bool>62ShowAnnotations("show-annotations",63cl::desc("Add informational comments to the .ll file"),64cl::cat(DisCategory));6566static cl::opt<bool> PreserveAssemblyUseListOrder(67"preserve-ll-uselistorder",68cl::desc("Preserve use-list order when writing LLVM assembly."),69cl::init(false), cl::Hidden, cl::cat(DisCategory));7071static cl::opt<bool>72MaterializeMetadata("materialize-metadata",73cl::desc("Load module without materializing metadata, "74"then materialize only the metadata"),75cl::cat(DisCategory));7677static cl::opt<bool> PrintThinLTOIndexOnly(78"print-thinlto-index-only",79cl::desc("Only read thinlto index and print the index as LLVM assembly."),80cl::init(false), cl::Hidden, cl::cat(DisCategory));8182extern cl::opt<bool> WriteNewDbgInfoFormat;8384extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat;8586namespace {8788static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {89OS << DL.getLine() << ":" << DL.getCol();90if (DILocation *IDL = DL.getInlinedAt()) {91OS << "@";92printDebugLoc(IDL, OS);93}94}95class CommentWriter : public AssemblyAnnotationWriter {96public:97void emitFunctionAnnot(const Function *F,98formatted_raw_ostream &OS) override {99OS << "; [#uses=" << F->getNumUses() << ']'; // Output # uses100OS << '\n';101}102void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {103bool Padded = false;104if (!V.getType()->isVoidTy()) {105OS.PadToColumn(50);106Padded = true;107// Output # uses and type108OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";109}110if (const Instruction *I = dyn_cast<Instruction>(&V)) {111if (const DebugLoc &DL = I->getDebugLoc()) {112if (!Padded) {113OS.PadToColumn(50);114Padded = true;115OS << ";";116}117OS << " [debug line = ";118printDebugLoc(DL,OS);119OS << "]";120}121if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {122if (!Padded) {123OS.PadToColumn(50);124OS << ";";125}126OS << " [debug variable = " << DDI->getVariable()->getName() << "]";127}128else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {129if (!Padded) {130OS.PadToColumn(50);131OS << ";";132}133OS << " [debug variable = " << DVI->getVariable()->getName() << "]";134}135}136}137};138139struct LLVMDisDiagnosticHandler : public DiagnosticHandler {140char *Prefix;141LLVMDisDiagnosticHandler(char *PrefixPtr) : Prefix(PrefixPtr) {}142bool handleDiagnostics(const DiagnosticInfo &DI) override {143raw_ostream &OS = errs();144OS << Prefix << ": ";145switch (DI.getSeverity()) {146case DS_Error: WithColor::error(OS); break;147case DS_Warning: WithColor::warning(OS); break;148case DS_Remark: OS << "remark: "; break;149case DS_Note: WithColor::note(OS); break;150}151152DiagnosticPrinterRawOStream DP(OS);153DI.print(DP);154OS << '\n';155156if (DI.getSeverity() == DS_Error)157exit(1);158return true;159}160};161} // end anon namespace162163static ExitOnError ExitOnErr;164165int main(int argc, char **argv) {166InitLLVM X(argc, argv);167168ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");169170cl::HideUnrelatedOptions({&DisCategory, &getColorCategory()});171cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");172173// Load bitcode into the new debug info format by default.174if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET)175LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE;176177LLVMContext Context;178Context.setDiagnosticHandler(179std::make_unique<LLVMDisDiagnosticHandler>(argv[0]));180181if (InputFilenames.size() < 1) {182InputFilenames.push_back("-");183} else if (InputFilenames.size() > 1 && !OutputFilename.empty()) {184errs()185<< "error: output file name cannot be set for multiple input files\n";186return 1;187}188189for (std::string InputFilename : InputFilenames) {190ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =191MemoryBuffer::getFileOrSTDIN(InputFilename);192if (std::error_code EC = BufferOrErr.getError()) {193WithColor::error() << InputFilename << ": " << EC.message() << '\n';194return 1;195}196std::unique_ptr<MemoryBuffer> MB = std::move(BufferOrErr.get());197198BitcodeFileContents IF = ExitOnErr(llvm::getBitcodeFileContents(*MB));199200const size_t N = IF.Mods.size();201202if (OutputFilename == "-" && N > 1)203errs() << "only single module bitcode files can be written to stdout\n";204205for (size_t I = 0; I < N; ++I) {206BitcodeModule MB = IF.Mods[I];207208std::unique_ptr<Module> M;209210if (!PrintThinLTOIndexOnly) {211M = ExitOnErr(212MB.getLazyModule(Context, MaterializeMetadata, SetImporting));213if (MaterializeMetadata)214ExitOnErr(M->materializeMetadata());215else216ExitOnErr(M->materializeAll());217}218219BitcodeLTOInfo LTOInfo = ExitOnErr(MB.getLTOInfo());220std::unique_ptr<ModuleSummaryIndex> Index;221if (LTOInfo.HasSummary)222Index = ExitOnErr(MB.getSummary());223224std::string FinalFilename(OutputFilename);225226// Just use stdout. We won't actually print anything on it.227if (DontPrint)228FinalFilename = "-";229230if (FinalFilename.empty()) { // Unspecified output, infer it.231if (InputFilename == "-") {232FinalFilename = "-";233} else {234StringRef IFN = InputFilename;235FinalFilename = (IFN.ends_with(".bc") ? IFN.drop_back(3) : IFN).str();236if (N > 1)237FinalFilename += std::string(".") + std::to_string(I);238FinalFilename += ".ll";239}240} else {241if (N > 1)242FinalFilename += std::string(".") + std::to_string(I);243}244245std::error_code EC;246std::unique_ptr<ToolOutputFile> Out(247new ToolOutputFile(FinalFilename, EC, sys::fs::OF_TextWithCRLF));248if (EC) {249errs() << EC.message() << '\n';250return 1;251}252253std::unique_ptr<AssemblyAnnotationWriter> Annotator;254if (ShowAnnotations)255Annotator.reset(new CommentWriter());256257// All that llvm-dis does is write the assembly to a file.258if (!DontPrint) {259if (M) {260M->setIsNewDbgInfoFormat(WriteNewDbgInfoFormat);261if (WriteNewDbgInfoFormat)262M->removeDebugIntrinsicDeclarations();263M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);264}265if (Index)266Index->print(Out->os());267}268269// Declare success.270Out->keep();271}272}273274return 0;275}276277278