llvm-as.cpp revision 195340
1//===--- llvm-as.cpp - The low-level LLVM assembler -----------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This utility may be invoked in the following manner:
11//   llvm-as --help         - Output information about command line switches
12//   llvm-as [options]      - Read LLVM asm from stdin, write bitcode to stdout
13//   llvm-as [options] x.ll - Read LLVM asm from the x.ll file, write bitcode
14//                            to the x.bc file.
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm/LLVMContext.h"
19#include "llvm/Module.h"
20#include "llvm/Assembly/Parser.h"
21#include "llvm/Analysis/Verifier.h"
22#include "llvm/Bitcode/ReaderWriter.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/ManagedStatic.h"
25#include "llvm/Support/PrettyStackTrace.h"
26#include "llvm/Support/SourceMgr.h"
27#include "llvm/Support/Streams.h"
28#include "llvm/Support/SystemUtils.h"
29#include "llvm/Support/raw_ostream.h"
30#include "llvm/System/Signals.h"
31#include <fstream>
32#include <iostream>
33#include <memory>
34using namespace llvm;
35
36static cl::opt<std::string>
37InputFilename(cl::Positional, cl::desc("<input .llvm file>"), cl::init("-"));
38
39static cl::opt<std::string>
40OutputFilename("o", cl::desc("Override output filename"),
41               cl::value_desc("filename"));
42
43static cl::opt<bool>
44Force("f", cl::desc("Overwrite output files"));
45
46static cl::opt<bool>
47DisableOutput("disable-output", cl::desc("Disable output"), cl::init(false));
48
49static cl::opt<bool>
50DumpAsm("d", cl::desc("Print assembly as parsed"), cl::Hidden);
51
52static cl::opt<bool>
53DisableVerify("disable-verify", cl::Hidden,
54              cl::desc("Do not run verifier on input LLVM (dangerous!)"));
55
56int main(int argc, char **argv) {
57  // Print a stack trace if we signal out.
58  sys::PrintStackTraceOnErrorSignal();
59  PrettyStackTraceProgram X(argc, argv);
60  LLVMContext Context;
61  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
62  cl::ParseCommandLineOptions(argc, argv, "llvm .ll -> .bc assembler\n");
63
64  int exitCode = 0;
65  std::ostream *Out = 0;
66  try {
67    // Parse the file now...
68    SMDiagnostic Err;
69    std::auto_ptr<Module> M(ParseAssemblyFile(InputFilename, Err, Context));
70    if (M.get() == 0) {
71      Err.Print(argv[0], errs());
72      return 1;
73    }
74
75    if (!DisableVerify) {
76      std::string Err;
77      if (verifyModule(*M.get(), ReturnStatusAction, &Err)) {
78        cerr << argv[0]
79             << ": assembly parsed, but does not verify as correct!\n";
80        cerr << Err;
81        return 1;
82      }
83    }
84
85    if (DumpAsm) cerr << "Here's the assembly:\n" << *M.get();
86
87    if (OutputFilename != "") {   // Specified an output filename?
88      if (OutputFilename != "-") {  // Not stdout?
89        if (!Force && std::ifstream(OutputFilename.c_str())) {
90          // If force is not specified, make sure not to overwrite a file!
91          cerr << argv[0] << ": error opening '" << OutputFilename
92               << "': file exists!\n"
93               << "Use -f command line argument to force output\n";
94          return 1;
95        }
96        Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
97                                std::ios::trunc | std::ios::binary);
98      } else {                      // Specified stdout
99        // FIXME: cout is not binary!
100        Out = &std::cout;
101      }
102    } else {
103      if (InputFilename == "-") {
104        OutputFilename = "-";
105        Out = &std::cout;
106      } else {
107        std::string IFN = InputFilename;
108        int Len = IFN.length();
109        if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') {
110          // Source ends in .ll
111          OutputFilename = std::string(IFN.begin(), IFN.end()-3);
112        } else {
113          OutputFilename = IFN;   // Append a .bc to it
114        }
115        OutputFilename += ".bc";
116
117        if (!Force && std::ifstream(OutputFilename.c_str())) {
118          // If force is not specified, make sure not to overwrite a file!
119          cerr << argv[0] << ": error opening '" << OutputFilename
120               << "': file exists!\n"
121               << "Use -f command line argument to force output\n";
122          return 1;
123        }
124
125        Out = new std::ofstream(OutputFilename.c_str(), std::ios::out |
126                                std::ios::trunc | std::ios::binary);
127        // Make sure that the Out file gets unlinked from the disk if we get a
128        // SIGINT
129        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
130      }
131    }
132
133    if (!Out->good()) {
134      cerr << argv[0] << ": error opening " << OutputFilename << "!\n";
135      return 1;
136    }
137
138    if (!DisableOutput)
139      if (Force || !CheckBitcodeOutputToConsole(Out,true))
140        WriteBitcodeToFile(M.get(), *Out);
141  } catch (const std::string& msg) {
142    cerr << argv[0] << ": " << msg << "\n";
143    exitCode = 1;
144  } catch (...) {
145    cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
146    exitCode = 1;
147  }
148
149  if (Out != &std::cout) delete Out;
150  return exitCode;
151}
152
153