diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp | 190 |
1 files changed, 126 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp index 0a670ab..49738a2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp @@ -46,14 +46,13 @@ namespace clang { const CodeGenOptions &CodeGenOpts; const TargetOptions &TargetOpts; const LangOptions &LangOpts; - raw_pwrite_stream *AsmOutStream; + std::unique_ptr<raw_pwrite_stream> AsmOutStream; ASTContext *Context; Timer LLVMIRGeneration; std::unique_ptr<CodeGenerator> Gen; - std::unique_ptr<llvm::Module> TheModule; SmallVector<std::pair<unsigned, std::unique_ptr<llvm::Module>>, 4> LinkModules; @@ -69,11 +68,12 @@ namespace clang { const TargetOptions &TargetOpts, const LangOptions &LangOpts, bool TimePasses, const std::string &InFile, const SmallVectorImpl<std::pair<unsigned, llvm::Module *>> &LinkModules, - raw_pwrite_stream *OS, LLVMContext &C, + std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) : Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts), - TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS), - Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"), + TargetOpts(TargetOpts), LangOpts(LangOpts), + AsmOutStream(std::move(OS)), Context(nullptr), + LLVMIRGeneration("LLVM IR Generation Time"), Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, CodeGenOpts, C, CoverageInfo)) { llvm::TimePassesIsEnabled = TimePasses; @@ -81,7 +81,10 @@ namespace clang { this->LinkModules.push_back( std::make_pair(I.first, std::unique_ptr<llvm::Module>(I.second))); } - std::unique_ptr<llvm::Module> takeModule() { return std::move(TheModule); } + llvm::Module *getModule() const { return Gen->GetModule(); } + std::unique_ptr<llvm::Module> takeModule() { + return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); + } void releaseLinkModules() { for (auto &I : LinkModules) I.second.release(); @@ -101,8 +104,6 @@ namespace clang { Gen->Initialize(Ctx); - TheModule.reset(Gen->GetModule()); - if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -123,14 +124,14 @@ namespace clang { return true; } - void HandleInlineMethodDefinition(CXXMethodDecl *D) override { + void HandleInlineFunctionDefinition(FunctionDecl *D) override { PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), - "LLVM IR generation of inline method"); + "LLVM IR generation of inline function"); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); - Gen->HandleInlineMethodDefinition(D); + Gen->HandleInlineFunctionDefinition(D); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); @@ -149,25 +150,12 @@ namespace clang { } // Silently ignore if we weren't initialized for some reason. - if (!TheModule) + if (!getModule()) return; - // Make sure IR generation is happy with the module. This is released by - // the module provider. - llvm::Module *M = Gen->ReleaseModule(); - if (!M) { - // The module has been released by IR gen on failures, do not double - // free. - TheModule.release(); - return; - } - - assert(TheModule.get() == M && - "Unexpected module change during IR generation"); - // Install an inline asm handler so that diagnostics get printed through // our diagnostics hooks. - LLVMContext &Ctx = TheModule->getContext(); + LLVMContext &Ctx = getModule()->getContext(); LLVMContext::InlineAsmDiagHandlerTy OldHandler = Ctx.getInlineAsmDiagnosticHandler(); void *OldContext = Ctx.getInlineAsmDiagnosticContext(); @@ -182,13 +170,15 @@ namespace clang { for (auto &I : LinkModules) { unsigned LinkFlags = I.first; CurLinkModule = I.second.get(); - if (Linker::linkModules(*M, std::move(I.second), LinkFlags)) + if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags)) return; } + EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); + EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, - C.getTargetInfo().getDataLayoutString(), - TheModule.get(), Action, AsmOutStream); + C.getTargetInfo().getDataLayout(), + getModule(), Action, std::move(AsmOutStream)); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); @@ -210,21 +200,12 @@ namespace clang { Gen->CompleteTentativeDefinition(D); } - void HandleVTable(CXXRecordDecl *RD) override { - Gen->HandleVTable(RD); - } - - void HandleLinkerOptionPragma(llvm::StringRef Opts) override { - Gen->HandleLinkerOptionPragma(Opts); + void AssignInheritanceModel(CXXRecordDecl *RD) override { + Gen->AssignInheritanceModel(RD); } - void HandleDetectMismatch(llvm::StringRef Name, - llvm::StringRef Value) override { - Gen->HandleDetectMismatch(Name, Value); - } - - void HandleDependentLibrary(llvm::StringRef Opts) override { - Gen->HandleDependentLibrary(Opts); + void HandleVTable(CXXRecordDecl *RD) override { + Gen->HandleVTable(RD); } static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, @@ -238,6 +219,13 @@ namespace clang { ((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI); } + /// Get the best possible source location to represent a diagnostic that + /// may have associated debug info. + const FullSourceLoc + getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithDebugLocBase &D, + bool &BadDebugInfo, StringRef &Filename, + unsigned &Line, unsigned &Column) const; + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, SourceLocation LocCookie); @@ -250,6 +238,8 @@ namespace clang { /// \return True if the diagnostic has been successfully reported, false /// otherwise. bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); + /// \brief Specialized handler for unsupported backend feature diagnostic. + void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); /// \brief Specialized handlers for optimization remarks. /// Note that these handlers only accept remarks and they always handle /// them. @@ -426,25 +416,21 @@ BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { return false; if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { + // FIXME: Shouldn't need to truncate to uint32_t Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), diag::warn_fe_frame_larger_than) - << D.getStackSize() << Decl::castToDeclContext(ND); + << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND); return true; } return false; } -void BackendConsumer::EmitOptimizationMessage( - const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { - // We only support warnings and remarks. - assert(D.getSeverity() == llvm::DS_Remark || - D.getSeverity() == llvm::DS_Warning); - +const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( + const llvm::DiagnosticInfoWithDebugLocBase &D, bool &BadDebugInfo, StringRef &Filename, + unsigned &Line, unsigned &Column) const { SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); - StringRef Filename; - unsigned Line, Column; SourceLocation DILoc; if (D.isLocationAvailable()) { @@ -455,6 +441,7 @@ void BackendConsumer::EmitOptimizationMessage( // source manager, so pass 1 if Column is not set. DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); } + BadDebugInfo = DILoc.isInvalid(); } // If a location isn't available, try to approximate it using the associated @@ -463,18 +450,63 @@ void BackendConsumer::EmitOptimizationMessage( FullSourceLoc Loc(DILoc, SourceMgr); if (Loc.isInvalid()) if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) - Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace()); + Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + + if (DILoc.isInvalid() && D.isLocationAvailable()) + // If we were not able to translate the file:line:col information + // back to a SourceLocation, at least emit a note stating that + // we could not translate this location. This can happen in the + // case of #line directives. + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) + << Filename << Line << Column; + + return Loc; +} + +void BackendConsumer::UnsupportedDiagHandler( + const llvm::DiagnosticInfoUnsupported &D) { + // We only support errors. + assert(D.getSeverity() == llvm::DS_Error); + + StringRef Filename; + unsigned Line, Column; + bool BadDebugInfo; + FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, + Line, Column); + + Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); + + if (BadDebugInfo) + // If we were not able to translate the file:line:col information + // back to a SourceLocation, at least emit a note stating that + // we could not translate this location. This can happen in the + // case of #line directives. + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) + << Filename << Line << Column; +} + +void BackendConsumer::EmitOptimizationMessage( + const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { + // We only support warnings and remarks. + assert(D.getSeverity() == llvm::DS_Remark || + D.getSeverity() == llvm::DS_Warning); + + StringRef Filename; + unsigned Line, Column; + bool BadDebugInfo = false; + FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, + Line, Column); Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName() ? D.getPassName() : "") << D.getMsg().str(); - if (DILoc.isInvalid() && D.isLocationAvailable()) + if (BadDebugInfo) // If we were not able to translate the file:line:col information // back to a SourceLocation, at least emit a note stating that // we could not translate this location. This can happen in the // case of #line directives. - Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc) + Diags.Report(Loc, diag::note_fe_backend_invalid_loc) << Filename << Line << Column; } @@ -504,7 +536,7 @@ void BackendConsumer::OptimizationRemarkHandler( // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a // regular expression that matches the name of the pass name in \p D. - if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint || + if (D.shouldAlwaysPrint() || (CodeGenOpts.OptimizationRemarkAnalysisPattern && CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) EmitOptimizationMessage( @@ -517,7 +549,7 @@ void BackendConsumer::OptimizationRemarkHandler( // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a // regular expression that matches the name of the pass name in \p D. - if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint || + if (D.shouldAlwaysPrint() || (CodeGenOpts.OptimizationRemarkAnalysisPattern && CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) EmitOptimizationMessage( @@ -530,7 +562,7 @@ void BackendConsumer::OptimizationRemarkHandler( // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a // regular expression that matches the name of the pass name in \p D. - if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint || + if (D.shouldAlwaysPrint() || (CodeGenOpts.OptimizationRemarkAnalysisPattern && CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) EmitOptimizationMessage( @@ -599,6 +631,9 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { // handler. OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); return; + case llvm::DK_Unsupported: + UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); + return; default: // Plugin IDs are not bound to any value as they are set dynamically. ComputeDiagRemarkID(Severity, backend_plugin, DiagID); @@ -657,7 +692,7 @@ llvm::LLVMContext *CodeGenAction::takeLLVMContext() { return VMContext; } -static raw_pwrite_stream * +static std::unique_ptr<raw_pwrite_stream> GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { switch (Action) { case Backend_EmitAssembly: @@ -680,7 +715,7 @@ GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { std::unique_ptr<ASTConsumer> CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { BackendAction BA = static_cast<BackendAction>(Act); - raw_pwrite_stream *OS = GetOutputStream(CI, InFile, BA); + std::unique_ptr<raw_pwrite_stream> OS = GetOutputStream(CI, InFile, BA); if (BA != Backend_EmitNothing && !OS) return nullptr; @@ -720,7 +755,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules, - OS, *VMContext, CoverageInfo)); + std::move(OS), *VMContext, CoverageInfo)); BEConsumer = Result.get(); return std::move(Result); } @@ -729,6 +764,22 @@ static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, void *Context, unsigned LocCookie) { SM.print(nullptr, llvm::errs()); + + auto Diags = static_cast<DiagnosticsEngine *>(Context); + unsigned DiagID; + switch (SM.getKind()) { + case llvm::SourceMgr::DK_Error: + DiagID = diag::err_fe_inline_asm; + break; + case llvm::SourceMgr::DK_Warning: + DiagID = diag::warn_fe_inline_asm; + break; + case llvm::SourceMgr::DK_Note: + DiagID = diag::note_fe_inline_asm; + break; + } + + Diags->Report(DiagID).AddString("cannot compile inline asm"); } void CodeGenAction::ExecuteAction() { @@ -736,7 +787,8 @@ void CodeGenAction::ExecuteAction() { if (getCurrentFileKind() == IK_LLVM_IR) { BackendAction BA = static_cast<BackendAction>(Act); CompilerInstance &CI = getCompilerInstance(); - raw_pwrite_stream *OS = GetOutputStream(CI, getCurrentFile(), BA); + std::unique_ptr<raw_pwrite_stream> OS = + GetOutputStream(CI, getCurrentFile(), BA); if (BA != Backend_EmitNothing && !OS) return; @@ -747,6 +799,11 @@ void CodeGenAction::ExecuteAction() { if (Invalid) return; + // For ThinLTO backend invocations, ensure that the context + // merges types based on ODR identifiers. + if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) + VMContext->enableDebugTypeODRUniquing(); + llvm::SMDiagnostic Err; TheModule = parseIR(MainFile->getMemBufferRef(), Err, *VMContext); if (!TheModule) { @@ -779,11 +836,16 @@ void CodeGenAction::ExecuteAction() { TheModule->setTargetTriple(TargetOpts.Triple); } + EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(), + MainFile->getMemBufferRef()); + LLVMContext &Ctx = TheModule->getContext(); - Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler); + Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, + &CI.getDiagnostics()); + EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts, - CI.getLangOpts(), CI.getTarget().getDataLayoutString(), - TheModule.get(), BA, OS); + CI.getLangOpts(), CI.getTarget().getDataLayout(), + TheModule.get(), BA, std::move(OS)); return; } |