diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:05 +0000 |
commit | 349cc55c9796c4596a5b9904cd3281af295f878f (patch) | |
tree | 410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp | |
parent | cb2ae6163174b90e999326ecec3699ee093a5d43 (diff) | |
parent | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp | 111 |
1 files changed, 87 insertions, 24 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp b/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp index b30bd11edbad..52c54d3c7a72 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp @@ -25,8 +25,10 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/Hashing.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -50,6 +52,8 @@ using namespace clang; using namespace llvm; +#define DEBUG_TYPE "codegenaction" + namespace clang { class BackendConsumer; class ClangDiagnosticHandler final : public DiagnosticHandler { @@ -125,6 +129,17 @@ namespace clang { SmallVector<LinkModule, 4> LinkModules; + // A map from mangled names to their function's source location, used for + // backend diagnostics as the Clang AST may be unavailable. We actually use + // the mangled name's hash as the key because mangled names can be very + // long and take up lots of space. Using a hash can cause name collision, + // but that is rare and the consequences are pointing to a wrong source + // location which is not severe. This is a vector instead of an actual map + // because we optimize for time building this map rather than time + // retrieving an entry, as backend diagnostics are uncommon. + std::vector<std::pair<llvm::hash_code, FullSourceLoc>> + ManglingFullSourceLocs; + // This is here so that the diagnostic printer knows the module a diagnostic // refers to. llvm::Module *CurLinkModule = nullptr; @@ -160,7 +175,7 @@ namespace clang { const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, - const LangOptions &LangOpts, + const LangOptions &LangOpts, llvm::Module *Module, SmallVector<LinkModule, 4> LinkModules, LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), @@ -170,7 +185,7 @@ namespace clang { LLVMIRGenerationRefCount(0), Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, CodeGenOpts, C, CoverageInfo)), - LinkModules(std::move(LinkModules)) { + LinkModules(std::move(LinkModules)), CurLinkModule(Module) { TimerIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; @@ -329,6 +344,27 @@ namespace clang { if (LinkInModules()) return; + for (auto &F : getModule()->functions()) { + if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { + auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + // TODO: use a fast content hash when available. + auto NameHash = llvm::hash_value(F.getName()); + ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); + } + } + + if (CodeGenOpts.ClearASTBeforeBackend) { + LLVM_DEBUG(llvm::dbgs() << "Clearing AST...\n"); + // Access to the AST is no longer available after this. + // Other things that the ASTContext manages are still available, e.g. + // the SourceManager. It'd be nice if we could separate out all the + // things in ASTContext used after this point and null out the + // ASTContext, but too many various parts of the ASTContext are still + // used in various parts. + C.cleanup(); + C.getAllocator().Reset(); + } + EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, @@ -375,6 +411,8 @@ namespace clang { bool &BadDebugInfo, StringRef &Filename, unsigned &Line, unsigned &Column) const; + Optional<FullSourceLoc> getFunctionSourceLocation(const Function &F) const; + void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); /// Specialized handler for InlineAsm diagnostic. /// \return True if the diagnostic has been successfully reported, false @@ -401,6 +439,7 @@ namespace clang { const llvm::OptimizationRemarkAnalysisAliasing &D); void OptimizationFailureHandler( const llvm::DiagnosticInfoOptimizationFailure &D); + void DontCallDiagHandler(const DiagnosticInfoDontCall &D); }; void BackendConsumer::anchor() {} @@ -567,17 +606,16 @@ BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { // We do not know how to format other severities. 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) - << static_cast<uint32_t>(D.getStackSize()) - << static_cast<uint32_t>(D.getStackLimit()) - << Decl::castToDeclContext(ND); - return true; - } + auto Loc = getFunctionSourceLocation(D.getFunction()); + if (!Loc) + return false; - return false; + // FIXME: Shouldn't need to truncate to uint32_t + Diags.Report(*Loc, diag::warn_fe_frame_larger_than) + << static_cast<uint32_t>(D.getStackSize()) + << static_cast<uint32_t>(D.getStackLimit()) + << llvm::demangle(D.getFunction().getName().str()); + return true; } const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( @@ -606,9 +644,10 @@ const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( // function definition. We use the definition's right brace to differentiate // from diagnostics that genuinely relate to the function itself. FullSourceLoc Loc(DILoc, SourceMgr); - if (Loc.isInvalid()) - if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) - Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + if (Loc.isInvalid()) { + if (auto MaybeLoc = getFunctionSourceLocation(D.getFunction())) + Loc = *MaybeLoc; + } if (DILoc.isInvalid() && D.isLocationAvailable()) // If we were not able to translate the file:line:col information @@ -621,6 +660,16 @@ const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( return Loc; } +Optional<FullSourceLoc> +BackendConsumer::getFunctionSourceLocation(const Function &F) const { + auto Hash = llvm::hash_value(F.getName()); + for (const auto &Pair : ManglingFullSourceLocs) { + if (Pair.first == Hash) + return Pair.second; + } + return Optional<FullSourceLoc>(); +} + void BackendConsumer::UnsupportedDiagHandler( const llvm::DiagnosticInfoUnsupported &D) { // We only support warnings or errors. @@ -758,6 +807,21 @@ void BackendConsumer::OptimizationFailureHandler( EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); } +void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) { + SourceLocation LocCookie = + SourceLocation::getFromRawEncoding(D.getLocCookie()); + + // FIXME: we can't yet diagnose indirect calls. When/if we can, we + // should instead assert that LocCookie.isValid(). + if (!LocCookie.isValid()) + return; + + Diags.Report(LocCookie, D.getSeverity() == DiagnosticSeverity::DS_Error + ? diag::err_fe_backend_error_attr + : diag::warn_fe_backend_warning_attr) + << llvm::demangle(D.getFunctionName().str()) << D.getNote(); +} + /// This function is invoked when the backend needs /// to report something to the user. void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { @@ -779,11 +843,7 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { ComputeDiagID(Severity, backend_frame_larger_than, DiagID); break; case DK_Linker: - assert(CurLinkModule); - // FIXME: stop eating the warnings and notes. - if (Severity != DS_Error) - return; - DiagID = diag::err_fe_cannot_link_module; + ComputeDiagID(Severity, linking_module, DiagID); break; case llvm::DK_OptimizationRemark: // Optimization remarks are always handled completely by this @@ -833,6 +893,9 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { case llvm::DK_Unsupported: UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); return; + case llvm::DK_DontCall: + DontCallDiagHandler(cast<DiagnosticInfoDontCall>(DI)); + return; default: // Plugin IDs are not bound to any value as they are set dynamically. ComputeDiagRemarkID(Severity, backend_plugin, DiagID); @@ -845,9 +908,9 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { DI.print(DP); } - if (DiagID == diag::err_fe_cannot_link_module) { - Diags.Report(diag::err_fe_cannot_link_module) - << CurLinkModule->getModuleIdentifier() << MsgStorage; + if (DI.getKind() == DK_Linker) { + assert(CurLinkModule && "CurLinkModule must be set for linker diagnostics"); + Diags.Report(DiagID) << CurLinkModule->getModuleIdentifier() << MsgStorage; return; } @@ -1088,7 +1151,7 @@ void CodeGenAction::ExecuteAction() { // BackendConsumer. BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), - CI.getTargetOpts(), CI.getLangOpts(), + CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(), std::move(LinkModules), *VMContext, nullptr); // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be // true here because the valued names are needed for reading textual IR. |