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