Index: clang/lib/CodeGen/CodeGenAction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenAction.cpp +++ clang/lib/CodeGen/CodeGenAction.cpp @@ -151,6 +151,25 @@ FrontendTimesIsEnabled = TimePasses; llvm::TimePassesIsEnabled = TimePasses; } + BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, + const LangOptions &LangOpts, bool TimePasses, + SmallVector LinkModules, LLVMContext &C, + CoverageSourceInfo *CoverageInfo = nullptr) + : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), + CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), + Context(nullptr), + LLVMIRGeneration("irgen", "LLVM IR Generation Time"), + LLVMIRGenerationRefCount(0), + Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, + CodeGenOpts, C, CoverageInfo)), + LinkModules(std::move(LinkModules)) { + FrontendTimesIsEnabled = TimePasses; + llvm::TimePassesIsEnabled = TimePasses; + } llvm::Module *getModule() const { return Gen->GetModule(); } std::unique_ptr takeModule() { return std::unique_ptr(Gen->ReleaseModule()); @@ -570,6 +589,12 @@ const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, StringRef &Filename, unsigned &Line, unsigned &Column) const { + // It's possible to have a null context in which case return an empty + // SourceLoc. + if (Context == nullptr) { + return FullSourceLoc(); + } + SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); SourceLocation DILoc; @@ -619,7 +644,16 @@ FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); - Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); + std::string Msg; + raw_string_ostream MsgStream(Msg); + if (!Loc.isValid()) { + MsgStream << D.getLocationStr() << ": in function " + << D.getFunction().getName() << ' ' + << *(D.getFunction().getFunctionType()) << ": "; + } + MsgStream << D.getMessage(); + + Diags.Report(Loc, diag::err_fe_backend_unsupported) << MsgStream.str(); if (BadDebugInfo) // If we were not able to translate the file:line:col information @@ -638,7 +672,12 @@ FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); - Diags.Report(Loc, diag::warn_profile_data_misexpect) << D.getMsg().str(); + std::string Msg; + if (!Loc.isValid()) + Msg = D.getLocationStr() + ": "; + raw_string_ostream MsgStream(Msg); + MsgStream << D.getMsg(); + Diags.Report(Loc, diag::warn_profile_data_misexpect) << MsgStream.str(); if (BadDebugInfo) // If we were not able to translate the file:line:col information @@ -662,6 +701,8 @@ getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); std::string Msg; + if (!Loc.isValid()) + Msg = "In " + D.getLocationStr() + ": "; raw_string_ostream MsgStream(Msg); MsgStream << D.getMsg(); @@ -1088,12 +1129,20 @@ Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, &Diagnostics); + // Set clang diagnostic handler. To do this we need to create a fake + // BackendConsumer. + BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getCodeGenOpts(), + CI.getTargetOpts(), CI.getLangOpts(), + CI.getFrontendOpts().ShowTimers, + std::move(LinkModules), *VMContext, nullptr); + Ctx.setDiagnosticHandler( + std::make_unique(CodeGenOpts, &Result)); + Expected> OptRecordFileOrErr = setupOptimizationRemarks( - Ctx, CodeGenOpts.OptRecordFile, - CodeGenOpts.OptRecordPasses, - CodeGenOpts.OptRecordFormat, - CodeGenOpts.DiagnosticsWithHotness, + Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, + CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, CodeGenOpts.DiagnosticsHotnessThreshold); if (Error E = OptRecordFileOrErr.takeError()) { @@ -1101,10 +1150,10 @@ return; } std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + std::move(*OptRecordFileOrErr); - EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), - CodeGenOpts, TargetOpts, CI.getLangOpts(), + EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, + TargetOpts, CI.getLangOpts(), CI.getTarget().getDataLayout(), TheModule.get(), BA, std::move(OS)); Index: clang/test/CodeGen/Inputs/thinlto_expect1.proftext =================================================================== --- /dev/null +++ clang/test/CodeGen/Inputs/thinlto_expect1.proftext @@ -0,0 +1,11 @@ +# IR level Instrumentation Flag +:ir +foo +# Func Hash: +25571299074 +# Num Counters: +2 +# Counter Values: +12 +24 + Index: clang/test/CodeGen/Inputs/thinlto_expect2.proftext =================================================================== --- /dev/null +++ clang/test/CodeGen/Inputs/thinlto_expect2.proftext @@ -0,0 +1,20 @@ +# CSIR level Instrumentation Flag +:csir +foo +# Func Hash: +25571299074 +# Num Counters: +2 +# Counter Values: +12 +24 + +foo +# Func Hash: +1152921530178146050 +# Num Counters: +2 +# Counter Values: +24 +12 + Index: clang/test/CodeGen/thinlto-clang-diagnostic-handler-in-be.c =================================================================== --- /dev/null +++ clang/test/CodeGen/thinlto-clang-diagnostic-handler-in-be.c @@ -0,0 +1,22 @@ +// Test clang diagnositic handler works in IR file compilaiton. + +// REQUIRES: x86-registered-target + +// RUN: llvm-profdata merge -o %t1.profdata %S/Inputs/thinlto_expect1.proftext +// RUN: %clang -O2 -fexperimental-new-pass-manager -flto=thin -g -fprofile-use=%t1.profdata -c -o %t1.bo %s +// RUN: llvm-lto -thinlto -o %t %t1.bo +// RUN: %clang -cc1 -O2 -fexperimental-new-pass-manager -x ir %t1.bo -fthinlto-index=%t.thinlto.bc -emit-obj -Rpass-analysis=info 2>&1 | FileCheck %s -check-prefix=CHECK-REMARK +// RUN: llvm-profdata merge -o %t2.profdata %S/Inputs/thinlto_expect2.proftext +// RUN: %clang -cc1 -O2 -fexperimental-new-pass-manager -x ir %t1.bo -fthinlto-index=%t.thinlto.bc -fprofile-instrument-use-path=%t2.profdata -emit-obj -Wmisexpect 2>&1 | FileCheck %s -check-prefix=CHECK-WARNING + +int sum; +__attribute__((noinline)) void bar() { + sum = 1234; +} + +__attribute__((noinline)) void foo(int m) { + if (__builtin_expect(m > 9, 1)) + bar(); +} +// CHECK-REMARK: remark: In {{.*}}.c: +// CHECK-WARNING: warning: Potential performance regression from use of __builtin_expect(): Annotation was correct on {{.*}}.c:{{[0-9]*}}:26: 50.00% (12 / 24) of profiled executions. Index: clang/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll =================================================================== --- clang/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll +++ clang/test/CodeGen/thinlto-diagnostic-handler-remarks-with-hotness.ll @@ -28,7 +28,7 @@ ; YAML-NEXT: ... ; Next try with pass remarks to stderr -; RUN: %clang -target x86_64-scei-ps4 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -mllvm -pass-remarks=inline -fdiagnostics-show-hotness -o %t2.o -c 2>&1 | FileCheck %s +; RUN: %clang -target x86_64-scei-ps4 -O2 -x ir %t.o -fthinlto-index=%t.thinlto.bc -Rpass=inline -fdiagnostics-show-hotness -o %t2.o -c 2>&1 | FileCheck %s ; CHECK: tinkywinky inlined into main with (cost=0, threshold=337) (hotness: 300)