cc1_main.cpp revision 204643
1//===-- cc1_main.cpp - Clang CC1 Driver -----------------------------------===//
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 is the entry point to the clang -cc1 functionality, which implements the
11// core compiler functionality along with a number of additional tools for
12// demonstration and testing purposes.
13//
14//===----------------------------------------------------------------------===//
15
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Driver/Arg.h"
18#include "clang/Driver/ArgList.h"
19#include "clang/Driver/CC1Options.h"
20#include "clang/Driver/DriverDiagnostic.h"
21#include "clang/Driver/OptTable.h"
22#include "clang/Frontend/CodeGenAction.h"
23#include "clang/Frontend/CompilerInstance.h"
24#include "clang/Frontend/CompilerInvocation.h"
25#include "clang/Frontend/FrontendActions.h"
26#include "clang/Frontend/FrontendDiagnostic.h"
27#include "clang/Frontend/FrontendPluginRegistry.h"
28#include "clang/Frontend/TextDiagnosticBuffer.h"
29#include "clang/Frontend/TextDiagnosticPrinter.h"
30#include "llvm/LLVMContext.h"
31#include "llvm/ADT/OwningPtr.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/ManagedStatic.h"
34#include "llvm/Support/raw_ostream.h"
35#include "llvm/System/DynamicLibrary.h"
36#include "llvm/Target/TargetSelect.h"
37#include <cstdio>
38using namespace clang;
39
40//===----------------------------------------------------------------------===//
41// Main driver
42//===----------------------------------------------------------------------===//
43
44void LLVMErrorHandler(void *UserData, const std::string &Message) {
45  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
46
47  Diags.Report(diag::err_fe_error_backend) << Message;
48
49  // We cannot recover from llvm errors.
50  exit(1);
51}
52
53static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
54  using namespace clang::frontend;
55
56  switch (CI.getFrontendOpts().ProgramAction) {
57  default:
58    llvm_unreachable("Invalid program action!");
59
60  case ASTDump:                return new ASTDumpAction();
61  case ASTPrint:               return new ASTPrintAction();
62  case ASTPrintXML:            return new ASTPrintXMLAction();
63  case ASTView:                return new ASTViewAction();
64  case DumpRawTokens:          return new DumpRawTokensAction();
65  case DumpRecordLayouts:      return new DumpRecordAction();
66  case DumpTokens:             return new DumpTokensAction();
67  case EmitAssembly:           return new EmitAssemblyAction();
68  case EmitBC:                 return new EmitBCAction();
69  case EmitHTML:               return new HTMLPrintAction();
70  case EmitLLVM:               return new EmitLLVMAction();
71  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
72  case EmitObj:                return new EmitObjAction();
73  case FixIt:                  return new FixItAction();
74  case GeneratePCH:            return new GeneratePCHAction();
75  case GeneratePTH:            return new GeneratePTHAction();
76  case InheritanceView:        return new InheritanceViewAction();
77  case ParseNoop:              return new ParseOnlyAction();
78  case ParsePrintCallbacks:    return new PrintParseAction();
79  case ParseSyntaxOnly:        return new SyntaxOnlyAction();
80
81  case PluginAction: {
82    if (CI.getFrontendOpts().ActionName == "help") {
83      llvm::errs() << "clang -cc1 plugins:\n";
84      for (FrontendPluginRegistry::iterator it =
85             FrontendPluginRegistry::begin(),
86             ie = FrontendPluginRegistry::end();
87           it != ie; ++it)
88        llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
89      return 0;
90    }
91
92    for (FrontendPluginRegistry::iterator it =
93           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
94         it != ie; ++it) {
95      if (it->getName() == CI.getFrontendOpts().ActionName)
96        return it->instantiate();
97    }
98
99    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
100      << CI.getFrontendOpts().ActionName;
101    return 0;
102  }
103
104  case PrintDeclContext:       return new DeclContextPrintAction();
105  case PrintPreprocessedInput: return new PrintPreprocessedAction();
106  case RewriteMacros:          return new RewriteMacrosAction();
107  case RewriteObjC:            return new RewriteObjCAction();
108  case RewriteTest:            return new RewriteTestAction();
109  case RunAnalysis:            return new AnalysisAction();
110  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
111  }
112}
113
114static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
115  // Create the underlying action.
116  FrontendAction *Act = CreateFrontendBaseAction(CI);
117  if (!Act)
118    return 0;
119
120  // If there are any AST files to merge, create a frontend action
121  // adaptor to perform the merge.
122  if (!CI.getFrontendOpts().ASTMergeFiles.empty())
123    Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
124                             CI.getFrontendOpts().ASTMergeFiles.size());
125
126  return Act;
127}
128
129// FIXME: Define the need for this testing away.
130static int cc1_test(Diagnostic &Diags,
131                    const char **ArgBegin, const char **ArgEnd) {
132  using namespace clang::driver;
133
134  llvm::errs() << "cc1 argv:";
135  for (const char **i = ArgBegin; i != ArgEnd; ++i)
136    llvm::errs() << " \"" << *i << '"';
137  llvm::errs() << "\n";
138
139  // Parse the arguments.
140  OptTable *Opts = createCC1OptTable();
141  unsigned MissingArgIndex, MissingArgCount;
142  InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd,
143                                       MissingArgIndex, MissingArgCount);
144
145  // Check for missing argument error.
146  if (MissingArgCount)
147    Diags.Report(clang::diag::err_drv_missing_argument)
148      << Args->getArgString(MissingArgIndex) << MissingArgCount;
149
150  // Dump the parsed arguments.
151  llvm::errs() << "cc1 parsed options:\n";
152  for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
153       it != ie; ++it)
154    (*it)->dump();
155
156  // Create a compiler invocation.
157  llvm::errs() << "cc1 creating invocation.\n";
158  CompilerInvocation Invocation;
159  CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags);
160
161  // Convert the invocation back to argument strings.
162  std::vector<std::string> InvocationArgs;
163  Invocation.toArgs(InvocationArgs);
164
165  // Dump the converted arguments.
166  llvm::SmallVector<const char*, 32> Invocation2Args;
167  llvm::errs() << "invocation argv :";
168  for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) {
169    Invocation2Args.push_back(InvocationArgs[i].c_str());
170    llvm::errs() << " \"" << InvocationArgs[i] << '"';
171  }
172  llvm::errs() << "\n";
173
174  // Convert those arguments to another invocation, and check that we got the
175  // same thing.
176  CompilerInvocation Invocation2;
177  CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
178                                     Invocation2Args.end(), Diags);
179
180  // FIXME: Implement CompilerInvocation comparison.
181  if (true) {
182    //llvm::errs() << "warning: Invocations differ!\n";
183
184    std::vector<std::string> Invocation2Args;
185    Invocation2.toArgs(Invocation2Args);
186    llvm::errs() << "invocation2 argv:";
187    for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i)
188      llvm::errs() << " \"" << Invocation2Args[i] << '"';
189    llvm::errs() << "\n";
190  }
191
192  return 0;
193}
194
195int cc1_main(const char **ArgBegin, const char **ArgEnd,
196             const char *Argv0, void *MainAddr) {
197  CompilerInstance Clang;
198
199  Clang.setLLVMContext(new llvm::LLVMContext);
200
201  // Run clang -cc1 test.
202  if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
203    TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
204    Diagnostic Diags(&DiagClient);
205    return cc1_test(Diags, ArgBegin + 1, ArgEnd);
206  }
207
208  // Initialize targets first, so that --version shows registered targets.
209  llvm::InitializeAllTargets();
210  llvm::InitializeAllAsmPrinters();
211
212  // Buffer diagnostics from argument parsing so that we can output them using a
213  // well formed diagnostic object.
214  TextDiagnosticBuffer DiagsBuffer;
215  Diagnostic Diags(&DiagsBuffer);
216  CompilerInvocation::CreateFromArgs(Clang.getInvocation(), ArgBegin, ArgEnd,
217                                     Diags);
218
219  // Infer the builtin include path if unspecified.
220  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
221      Clang.getHeaderSearchOpts().ResourceDir.empty())
222    Clang.getHeaderSearchOpts().ResourceDir =
223      CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
224
225  // Honor -help.
226  if (Clang.getFrontendOpts().ShowHelp) {
227    llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
228    Opts->PrintHelp(llvm::outs(), "clang -cc1",
229                    "LLVM 'Clang' Compiler: http://clang.llvm.org");
230    return 0;
231  }
232
233  // Honor -version.
234  //
235  // FIXME: Use a better -version message?
236  if (Clang.getFrontendOpts().ShowVersion) {
237    llvm::cl::PrintVersionMessage();
238    return 0;
239  }
240
241  // Create the actual diagnostics engine.
242  Clang.createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
243  if (!Clang.hasDiagnostics())
244    return 1;
245
246  // Set an error handler, so that any LLVM backend diagnostics go through our
247  // error handler.
248  llvm::llvm_install_error_handler(LLVMErrorHandler,
249                                   static_cast<void*>(&Clang.getDiagnostics()));
250
251  DiagsBuffer.FlushDiagnostics(Clang.getDiagnostics());
252
253  // Load any requested plugins.
254  for (unsigned i = 0,
255         e = Clang.getFrontendOpts().Plugins.size(); i != e; ++i) {
256    const std::string &Path = Clang.getFrontendOpts().Plugins[i];
257    std::string Error;
258    if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
259      Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
260  }
261
262  // If there were errors in processing arguments, don't do anything else.
263  bool Success = false;
264  if (!Clang.getDiagnostics().getNumErrors()) {
265    // Create and execute the frontend action.
266    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
267    if (Act)
268      Success = Clang.ExecuteAction(*Act);
269  }
270
271  // Managed static deconstruction. Useful for making things like
272  // -time-passes usable.
273  llvm::llvm_shutdown();
274
275  return !Success;
276}
277