clang API Documentation
00001 //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/CodeGen/CodeGenAction.h" 00011 #include "clang/Basic/FileManager.h" 00012 #include "clang/Basic/SourceManager.h" 00013 #include "clang/Basic/TargetInfo.h" 00014 #include "clang/AST/ASTConsumer.h" 00015 #include "clang/AST/ASTContext.h" 00016 #include "clang/AST/DeclGroup.h" 00017 #include "clang/CodeGen/BackendUtil.h" 00018 #include "clang/CodeGen/ModuleBuilder.h" 00019 #include "clang/Frontend/CompilerInstance.h" 00020 #include "clang/Frontend/FrontendDiagnostic.h" 00021 #include "llvm/LLVMContext.h" 00022 #include "llvm/Linker.h" 00023 #include "llvm/Module.h" 00024 #include "llvm/Pass.h" 00025 #include "llvm/ADT/OwningPtr.h" 00026 #include "llvm/ADT/SmallString.h" 00027 #include "llvm/Bitcode/ReaderWriter.h" 00028 #include "llvm/Support/IRReader.h" 00029 #include "llvm/Support/MemoryBuffer.h" 00030 #include "llvm/Support/SourceMgr.h" 00031 #include "llvm/Support/Timer.h" 00032 using namespace clang; 00033 using namespace llvm; 00034 00035 namespace clang { 00036 class BackendConsumer : public ASTConsumer { 00037 virtual void anchor(); 00038 DiagnosticsEngine &Diags; 00039 BackendAction Action; 00040 const CodeGenOptions &CodeGenOpts; 00041 const TargetOptions &TargetOpts; 00042 const LangOptions &LangOpts; 00043 raw_ostream *AsmOutStream; 00044 ASTContext *Context; 00045 00046 Timer LLVMIRGeneration; 00047 00048 OwningPtr<CodeGenerator> Gen; 00049 00050 OwningPtr<llvm::Module> TheModule, LinkModule; 00051 00052 public: 00053 BackendConsumer(BackendAction action, DiagnosticsEngine &_Diags, 00054 const CodeGenOptions &compopts, 00055 const TargetOptions &targetopts, 00056 const LangOptions &langopts, 00057 bool TimePasses, 00058 const std::string &infile, 00059 llvm::Module *LinkModule, 00060 raw_ostream *OS, 00061 LLVMContext &C) : 00062 Diags(_Diags), 00063 Action(action), 00064 CodeGenOpts(compopts), 00065 TargetOpts(targetopts), 00066 LangOpts(langopts), 00067 AsmOutStream(OS), 00068 LLVMIRGeneration("LLVM IR Generation Time"), 00069 Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)), 00070 LinkModule(LinkModule) { 00071 llvm::TimePassesIsEnabled = TimePasses; 00072 } 00073 00074 llvm::Module *takeModule() { return TheModule.take(); } 00075 llvm::Module *takeLinkModule() { return LinkModule.take(); } 00076 00077 virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { 00078 Gen->HandleCXXStaticMemberVarInstantiation(VD); 00079 } 00080 00081 virtual void Initialize(ASTContext &Ctx) { 00082 Context = &Ctx; 00083 00084 if (llvm::TimePassesIsEnabled) 00085 LLVMIRGeneration.startTimer(); 00086 00087 Gen->Initialize(Ctx); 00088 00089 TheModule.reset(Gen->GetModule()); 00090 00091 if (llvm::TimePassesIsEnabled) 00092 LLVMIRGeneration.stopTimer(); 00093 } 00094 00095 virtual bool HandleTopLevelDecl(DeclGroupRef D) { 00096 PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), 00097 Context->getSourceManager(), 00098 "LLVM IR generation of declaration"); 00099 00100 if (llvm::TimePassesIsEnabled) 00101 LLVMIRGeneration.startTimer(); 00102 00103 Gen->HandleTopLevelDecl(D); 00104 00105 if (llvm::TimePassesIsEnabled) 00106 LLVMIRGeneration.stopTimer(); 00107 00108 return true; 00109 } 00110 00111 virtual void HandleTranslationUnit(ASTContext &C) { 00112 { 00113 PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); 00114 if (llvm::TimePassesIsEnabled) 00115 LLVMIRGeneration.startTimer(); 00116 00117 Gen->HandleTranslationUnit(C); 00118 00119 if (llvm::TimePassesIsEnabled) 00120 LLVMIRGeneration.stopTimer(); 00121 } 00122 00123 // Silently ignore if we weren't initialized for some reason. 00124 if (!TheModule) 00125 return; 00126 00127 // Make sure IR generation is happy with the module. This is released by 00128 // the module provider. 00129 llvm::Module *M = Gen->ReleaseModule(); 00130 if (!M) { 00131 // The module has been released by IR gen on failures, do not double 00132 // free. 00133 TheModule.take(); 00134 return; 00135 } 00136 00137 assert(TheModule.get() == M && 00138 "Unexpected module change during IR generation"); 00139 00140 // Link LinkModule into this module if present, preserving its validity. 00141 if (LinkModule) { 00142 std::string ErrorMsg; 00143 if (Linker::LinkModules(M, LinkModule.get(), Linker::PreserveSource, 00144 &ErrorMsg)) { 00145 Diags.Report(diag::err_fe_cannot_link_module) 00146 << LinkModule->getModuleIdentifier() << ErrorMsg; 00147 return; 00148 } 00149 } 00150 00151 // Install an inline asm handler so that diagnostics get printed through 00152 // our diagnostics hooks. 00153 LLVMContext &Ctx = TheModule->getContext(); 00154 LLVMContext::InlineAsmDiagHandlerTy OldHandler = 00155 Ctx.getInlineAsmDiagnosticHandler(); 00156 void *OldContext = Ctx.getInlineAsmDiagnosticContext(); 00157 Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); 00158 00159 EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, 00160 TheModule.get(), Action, AsmOutStream); 00161 00162 Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); 00163 } 00164 00165 virtual void HandleTagDeclDefinition(TagDecl *D) { 00166 PrettyStackTraceDecl CrashInfo(D, SourceLocation(), 00167 Context->getSourceManager(), 00168 "LLVM IR generation of declaration"); 00169 Gen->HandleTagDeclDefinition(D); 00170 } 00171 00172 virtual void CompleteTentativeDefinition(VarDecl *D) { 00173 Gen->CompleteTentativeDefinition(D); 00174 } 00175 00176 virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) { 00177 Gen->HandleVTable(RD, DefinitionRequired); 00178 } 00179 00180 static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, 00181 unsigned LocCookie) { 00182 SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); 00183 ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); 00184 } 00185 00186 void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, 00187 SourceLocation LocCookie); 00188 }; 00189 00190 void BackendConsumer::anchor() {} 00191 } 00192 00193 /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr 00194 /// buffer to be a valid FullSourceLoc. 00195 static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, 00196 SourceManager &CSM) { 00197 // Get both the clang and llvm source managers. The location is relative to 00198 // a memory buffer that the LLVM Source Manager is handling, we need to add 00199 // a copy to the Clang source manager. 00200 const llvm::SourceMgr &LSM = *D.getSourceMgr(); 00201 00202 // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr 00203 // already owns its one and clang::SourceManager wants to own its one. 00204 const MemoryBuffer *LBuf = 00205 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); 00206 00207 // Create the copy and transfer ownership to clang::SourceManager. 00208 llvm::MemoryBuffer *CBuf = 00209 llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), 00210 LBuf->getBufferIdentifier()); 00211 FileID FID = CSM.createFileIDForMemBuffer(CBuf); 00212 00213 // Translate the offset into the file. 00214 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); 00215 SourceLocation NewLoc = 00216 CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); 00217 return FullSourceLoc(NewLoc, CSM); 00218 } 00219 00220 00221 /// InlineAsmDiagHandler2 - This function is invoked when the backend hits an 00222 /// error parsing inline asm. The SMDiagnostic indicates the error relative to 00223 /// the temporary memory buffer that the inline asm parser has set up. 00224 void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, 00225 SourceLocation LocCookie) { 00226 // There are a couple of different kinds of errors we could get here. First, 00227 // we re-format the SMDiagnostic in terms of a clang diagnostic. 00228 00229 // Strip "error: " off the start of the message string. 00230 StringRef Message = D.getMessage(); 00231 if (Message.startswith("error: ")) 00232 Message = Message.substr(7); 00233 00234 // If the SMDiagnostic has an inline asm source location, translate it. 00235 FullSourceLoc Loc; 00236 if (D.getLoc() != SMLoc()) 00237 Loc = ConvertBackendLocation(D, Context->getSourceManager()); 00238 00239 00240 // If this problem has clang-level source location information, report the 00241 // issue as being an error in the source with a note showing the instantiated 00242 // code. 00243 if (LocCookie.isValid()) { 00244 Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message); 00245 00246 if (D.getLoc().isValid()) { 00247 DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); 00248 // Convert the SMDiagnostic ranges into SourceRange and attach them 00249 // to the diagnostic. 00250 for (unsigned i = 0, e = D.getRanges().size(); i != e; ++i) { 00251 std::pair<unsigned, unsigned> Range = D.getRanges()[i]; 00252 unsigned Column = D.getColumnNo(); 00253 B << SourceRange(Loc.getLocWithOffset(Range.first - Column), 00254 Loc.getLocWithOffset(Range.second - Column)); 00255 } 00256 } 00257 return; 00258 } 00259 00260 // Otherwise, report the backend error as occurring in the generated .s file. 00261 // If Loc is invalid, we still need to report the error, it just gets no 00262 // location info. 00263 Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); 00264 } 00265 00266 // 00267 00268 CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) 00269 : Act(_Act), LinkModule(0), 00270 VMContext(_VMContext ? _VMContext : new LLVMContext), 00271 OwnsVMContext(!_VMContext) {} 00272 00273 CodeGenAction::~CodeGenAction() { 00274 TheModule.reset(); 00275 if (OwnsVMContext) 00276 delete VMContext; 00277 } 00278 00279 bool CodeGenAction::hasIRSupport() const { return true; } 00280 00281 void CodeGenAction::EndSourceFileAction() { 00282 // If the consumer creation failed, do nothing. 00283 if (!getCompilerInstance().hasASTConsumer()) 00284 return; 00285 00286 // If we were given a link module, release consumer's ownership of it. 00287 if (LinkModule) 00288 BEConsumer->takeLinkModule(); 00289 00290 // Steal the module from the consumer. 00291 TheModule.reset(BEConsumer->takeModule()); 00292 } 00293 00294 llvm::Module *CodeGenAction::takeModule() { 00295 return TheModule.take(); 00296 } 00297 00298 llvm::LLVMContext *CodeGenAction::takeLLVMContext() { 00299 OwnsVMContext = false; 00300 return VMContext; 00301 } 00302 00303 static raw_ostream *GetOutputStream(CompilerInstance &CI, 00304 StringRef InFile, 00305 BackendAction Action) { 00306 switch (Action) { 00307 case Backend_EmitAssembly: 00308 return CI.createDefaultOutputFile(false, InFile, "s"); 00309 case Backend_EmitLL: 00310 return CI.createDefaultOutputFile(false, InFile, "ll"); 00311 case Backend_EmitBC: 00312 return CI.createDefaultOutputFile(true, InFile, "bc"); 00313 case Backend_EmitNothing: 00314 return 0; 00315 case Backend_EmitMCNull: 00316 case Backend_EmitObj: 00317 return CI.createDefaultOutputFile(true, InFile, "o"); 00318 } 00319 00320 llvm_unreachable("Invalid action!"); 00321 } 00322 00323 ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, 00324 StringRef InFile) { 00325 BackendAction BA = static_cast<BackendAction>(Act); 00326 OwningPtr<raw_ostream> OS(GetOutputStream(CI, InFile, BA)); 00327 if (BA != Backend_EmitNothing && !OS) 00328 return 0; 00329 00330 llvm::Module *LinkModuleToUse = LinkModule; 00331 00332 // If we were not given a link module, and the user requested that one be 00333 // loaded from bitcode, do so now. 00334 const std::string &LinkBCFile = CI.getCodeGenOpts().LinkBitcodeFile; 00335 if (!LinkModuleToUse && !LinkBCFile.empty()) { 00336 std::string ErrorStr; 00337 00338 llvm::MemoryBuffer *BCBuf = 00339 CI.getFileManager().getBufferForFile(LinkBCFile, &ErrorStr); 00340 if (!BCBuf) { 00341 CI.getDiagnostics().Report(diag::err_cannot_open_file) 00342 << LinkBCFile << ErrorStr; 00343 return 0; 00344 } 00345 00346 LinkModuleToUse = getLazyBitcodeModule(BCBuf, *VMContext, &ErrorStr); 00347 if (!LinkModuleToUse) { 00348 CI.getDiagnostics().Report(diag::err_cannot_open_file) 00349 << LinkBCFile << ErrorStr; 00350 return 0; 00351 } 00352 } 00353 00354 BEConsumer = 00355 new BackendConsumer(BA, CI.getDiagnostics(), 00356 CI.getCodeGenOpts(), CI.getTargetOpts(), 00357 CI.getLangOpts(), 00358 CI.getFrontendOpts().ShowTimers, InFile, 00359 LinkModuleToUse, OS.take(), *VMContext); 00360 return BEConsumer; 00361 } 00362 00363 void CodeGenAction::ExecuteAction() { 00364 // If this is an IR file, we have to treat it specially. 00365 if (getCurrentFileKind() == IK_LLVM_IR) { 00366 BackendAction BA = static_cast<BackendAction>(Act); 00367 CompilerInstance &CI = getCompilerInstance(); 00368 raw_ostream *OS = GetOutputStream(CI, getCurrentFile(), BA); 00369 if (BA != Backend_EmitNothing && !OS) 00370 return; 00371 00372 bool Invalid; 00373 SourceManager &SM = CI.getSourceManager(); 00374 const llvm::MemoryBuffer *MainFile = SM.getBuffer(SM.getMainFileID(), 00375 &Invalid); 00376 if (Invalid) 00377 return; 00378 00379 // FIXME: This is stupid, IRReader shouldn't take ownership. 00380 llvm::MemoryBuffer *MainFileCopy = 00381 llvm::MemoryBuffer::getMemBufferCopy(MainFile->getBuffer(), 00382 getCurrentFile().c_str()); 00383 00384 llvm::SMDiagnostic Err; 00385 TheModule.reset(ParseIR(MainFileCopy, Err, *VMContext)); 00386 if (!TheModule) { 00387 // Translate from the diagnostic info to the SourceManager location. 00388 SourceLocation Loc = SM.translateFileLineCol( 00389 SM.getFileEntryForID(SM.getMainFileID()), Err.getLineNo(), 00390 Err.getColumnNo() + 1); 00391 00392 // Get a custom diagnostic for the error. We strip off a leading 00393 // diagnostic code if there is one. 00394 StringRef Msg = Err.getMessage(); 00395 if (Msg.startswith("error: ")) 00396 Msg = Msg.substr(7); 00397 00398 // Escape '%', which is interpreted as a format character. 00399 llvm::SmallString<128> EscapedMessage; 00400 for (unsigned i = 0, e = Msg.size(); i != e; ++i) { 00401 if (Msg[i] == '%') 00402 EscapedMessage += '%'; 00403 EscapedMessage += Msg[i]; 00404 } 00405 00406 unsigned DiagID = CI.getDiagnostics().getCustomDiagID( 00407 DiagnosticsEngine::Error, EscapedMessage); 00408 00409 CI.getDiagnostics().Report(Loc, DiagID); 00410 return; 00411 } 00412 00413 EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), 00414 CI.getTargetOpts(), CI.getLangOpts(), 00415 TheModule.get(), 00416 BA, OS); 00417 return; 00418 } 00419 00420 // Otherwise follow the normal AST path. 00421 this->ASTFrontendAction::ExecuteAction(); 00422 } 00423 00424 // 00425 00426 void EmitAssemblyAction::anchor() { } 00427 EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) 00428 : CodeGenAction(Backend_EmitAssembly, _VMContext) {} 00429 00430 void EmitBCAction::anchor() { } 00431 EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) 00432 : CodeGenAction(Backend_EmitBC, _VMContext) {} 00433 00434 void EmitLLVMAction::anchor() { } 00435 EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) 00436 : CodeGenAction(Backend_EmitLL, _VMContext) {} 00437 00438 void EmitLLVMOnlyAction::anchor() { } 00439 EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) 00440 : CodeGenAction(Backend_EmitNothing, _VMContext) {} 00441 00442 void EmitCodeGenOnlyAction::anchor() { } 00443 EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) 00444 : CodeGenAction(Backend_EmitMCNull, _VMContext) {} 00445 00446 void EmitObjAction::anchor() { } 00447 EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) 00448 : CodeGenAction(Backend_EmitObj, _VMContext) {}