10b57cec5SDimitry Andric //===--- llvm-as.cpp - The low-level LLVM assembler -----------------------===// 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 utility may be invoked in the following manner: 100b57cec5SDimitry Andric // llvm-as --help - Output information about command line switches 110b57cec5SDimitry Andric // llvm-as [options] - Read LLVM asm from stdin, write bitcode to stdout 120b57cec5SDimitry Andric // llvm-as [options] x.ll - Read LLVM asm from the x.ll file, write bitcode 130b57cec5SDimitry Andric // to the x.bc file. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "llvm/AsmParser/Parser.h" 180b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriter.h" 190b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 200b57cec5SDimitry Andric #include "llvm/IR/Module.h" 210b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h" 220b57cec5SDimitry Andric #include "llvm/IR/Verifier.h" 230b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 240b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 250b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h" 260b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 270b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 280b57cec5SDimitry Andric #include "llvm/Support/SystemUtils.h" 290b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h" 300b57cec5SDimitry Andric #include <memory> 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric cl::OptionCategory AsCat("llvm-as Options"); 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric static cl::opt<std::string> InputFilename(cl::Positional, 360b57cec5SDimitry Andric cl::desc("<input .llvm file>"), 370b57cec5SDimitry Andric cl::init("-")); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric static cl::opt<std::string> OutputFilename("o", 400b57cec5SDimitry Andric cl::desc("Override output filename"), 410b57cec5SDimitry Andric cl::value_desc("filename"), 420b57cec5SDimitry Andric cl::cat(AsCat)); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric static cl::opt<bool> Force("f", cl::desc("Enable binary output on terminals"), 450b57cec5SDimitry Andric cl::cat(AsCat)); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric static cl::opt<bool> DisableOutput("disable-output", cl::desc("Disable output"), 480b57cec5SDimitry Andric cl::init(false), cl::cat(AsCat)); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric static cl::opt<bool> EmitModuleHash("module-hash", cl::desc("Emit module hash"), 510b57cec5SDimitry Andric cl::init(false), cl::cat(AsCat)); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric static cl::opt<bool> DumpAsm("d", cl::desc("Print assembly as parsed"), 540b57cec5SDimitry Andric cl::Hidden, cl::cat(AsCat)); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric static cl::opt<bool> 570b57cec5SDimitry Andric DisableVerify("disable-verify", cl::Hidden, 580b57cec5SDimitry Andric cl::desc("Do not run verifier on input LLVM (dangerous!)"), 590b57cec5SDimitry Andric cl::cat(AsCat)); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric static cl::opt<bool> PreserveBitcodeUseListOrder( 620b57cec5SDimitry Andric "preserve-bc-uselistorder", 630b57cec5SDimitry Andric cl::desc("Preserve use-list order when writing LLVM bitcode."), 640b57cec5SDimitry Andric cl::init(true), cl::Hidden, cl::cat(AsCat)); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static cl::opt<std::string> ClDataLayout("data-layout", 670b57cec5SDimitry Andric cl::desc("data layout string to use"), 680b57cec5SDimitry Andric cl::value_desc("layout-string"), 690b57cec5SDimitry Andric cl::init(""), cl::cat(AsCat)); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric static void WriteOutputFile(const Module *M, const ModuleSummaryIndex *Index) { 720b57cec5SDimitry Andric // Infer the output filename if needed. 730b57cec5SDimitry Andric if (OutputFilename.empty()) { 740b57cec5SDimitry Andric if (InputFilename == "-") { 750b57cec5SDimitry Andric OutputFilename = "-"; 760b57cec5SDimitry Andric } else { 770b57cec5SDimitry Andric StringRef IFN = InputFilename; 780b57cec5SDimitry Andric OutputFilename = (IFN.endswith(".ll") ? IFN.drop_back(3) : IFN).str(); 790b57cec5SDimitry Andric OutputFilename += ".bc"; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric std::error_code EC; 840b57cec5SDimitry Andric std::unique_ptr<ToolOutputFile> Out( 858bcb0991SDimitry Andric new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); 860b57cec5SDimitry Andric if (EC) { 870b57cec5SDimitry Andric errs() << EC.message() << '\n'; 880b57cec5SDimitry Andric exit(1); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 91*5ffd83dbSDimitry Andric if (Force || !CheckBitcodeOutputToConsole(Out->os())) { 920b57cec5SDimitry Andric const ModuleSummaryIndex *IndexToWrite = nullptr; 93*5ffd83dbSDimitry Andric // Don't attempt to write a summary index unless it contains any entries or 94*5ffd83dbSDimitry Andric // has non-zero flags. The latter is used to assemble dummy index files for 95*5ffd83dbSDimitry Andric // skipping modules by distributed ThinLTO backends. Otherwise we get an empty 96*5ffd83dbSDimitry Andric // summary section. 97*5ffd83dbSDimitry Andric if (Index && (Index->begin() != Index->end() || Index->getFlags())) 980b57cec5SDimitry Andric IndexToWrite = Index; 990b57cec5SDimitry Andric if (!IndexToWrite || (M && (!M->empty() || !M->global_empty()))) 1000b57cec5SDimitry Andric // If we have a non-empty Module, then we write the Module plus 1010b57cec5SDimitry Andric // any non-null Index along with it as a per-module Index. 1020b57cec5SDimitry Andric // If both are empty, this will give an empty module block, which is 1030b57cec5SDimitry Andric // the expected behavior. 1040b57cec5SDimitry Andric WriteBitcodeToFile(*M, Out->os(), PreserveBitcodeUseListOrder, 1050b57cec5SDimitry Andric IndexToWrite, EmitModuleHash); 1060b57cec5SDimitry Andric else 1070b57cec5SDimitry Andric // Otherwise, with an empty Module but non-empty Index, we write a 1080b57cec5SDimitry Andric // combined index. 1090b57cec5SDimitry Andric WriteIndexToFile(*IndexToWrite, Out->os()); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric // Declare success. 1130b57cec5SDimitry Andric Out->keep(); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric int main(int argc, char **argv) { 1170b57cec5SDimitry Andric InitLLVM X(argc, argv); 1180b57cec5SDimitry Andric LLVMContext Context; 1190b57cec5SDimitry Andric cl::HideUnrelatedOptions(AsCat); 1200b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n"); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Parse the file now... 1230b57cec5SDimitry Andric SMDiagnostic Err; 124*5ffd83dbSDimitry Andric auto SetDataLayout = [](StringRef) -> Optional<std::string> { 125*5ffd83dbSDimitry Andric if (ClDataLayout.empty()) 126*5ffd83dbSDimitry Andric return None; 127*5ffd83dbSDimitry Andric return ClDataLayout; 128*5ffd83dbSDimitry Andric }; 129*5ffd83dbSDimitry Andric ParsedModuleAndIndex ModuleAndIndex; 130*5ffd83dbSDimitry Andric if (DisableVerify) { 131*5ffd83dbSDimitry Andric ModuleAndIndex = parseAssemblyFileWithIndexNoUpgradeDebugInfo( 132*5ffd83dbSDimitry Andric InputFilename, Err, Context, nullptr, SetDataLayout); 133*5ffd83dbSDimitry Andric } else { 134*5ffd83dbSDimitry Andric ModuleAndIndex = parseAssemblyFileWithIndex(InputFilename, Err, Context, 135*5ffd83dbSDimitry Andric nullptr, SetDataLayout); 136*5ffd83dbSDimitry Andric } 1370b57cec5SDimitry Andric std::unique_ptr<Module> M = std::move(ModuleAndIndex.Mod); 1380b57cec5SDimitry Andric if (!M.get()) { 1390b57cec5SDimitry Andric Err.print(argv[0], errs()); 1400b57cec5SDimitry Andric return 1; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric std::unique_ptr<ModuleSummaryIndex> Index = std::move(ModuleAndIndex.Index); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric if (!DisableVerify) { 1450b57cec5SDimitry Andric std::string ErrorStr; 1460b57cec5SDimitry Andric raw_string_ostream OS(ErrorStr); 1470b57cec5SDimitry Andric if (verifyModule(*M.get(), &OS)) { 1480b57cec5SDimitry Andric errs() << argv[0] 1490b57cec5SDimitry Andric << ": assembly parsed, but does not verify as correct!\n"; 1500b57cec5SDimitry Andric errs() << OS.str(); 1510b57cec5SDimitry Andric return 1; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric // TODO: Implement and call summary index verifier. 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric if (DumpAsm) { 1570b57cec5SDimitry Andric errs() << "Here's the assembly:\n" << *M.get(); 1580b57cec5SDimitry Andric if (Index.get() && Index->begin() != Index->end()) 1590b57cec5SDimitry Andric Index->print(errs()); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric if (!DisableOutput) 1630b57cec5SDimitry Andric WriteOutputFile(M.get(), Index.get()); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric return 0; 1660b57cec5SDimitry Andric } 167