llvm.org GIT mirror llvm / 18b4c37
This patch fixes https://bugs.llvm.org/show_bug.cgi?id=32352 It enables OptimizationRemarkEmitter::allowExtraAnalysis and MachineOptimizationRemarkEmitter::allowExtraAnalysis to return true not only for -fsave-optimization-record but when specific remarks are requested with command line options. The diagnostic handler used to be callback now this patch adds a class DiagnosticHandler. It has virtual method to provide custom diagnostic handler and methods to control which particular remarks are enabled. However LLVM-C API users can still provide callback function for diagnostic handler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313390 91177308-0d34-0410-b5e6-96231b3b80d8 Vivek Pandya 2 years ago
23 changed file(s) with 424 addition(s) and 255 deletion(s). Raw diff Collapse all Expand all
6666 bool invalidate(Function &F, const PreservedAnalyses &PA,
6767 FunctionAnalysisManager::Invalidator &Inv);
6868
69 /// \brief Output the remark to the optimization record file. Also send it to
70 /// the diagnostic handler if remarks are requested for the pass.
69 /// \brief Output the remark via the diagnostic handler and to the
70 /// optimization record file.
7171 void emit(DiagnosticInfoOptimizationBase &OptDiag);
7272
7373 /// \brief Whether we allow for extra compile-time budget to perform more
7777 /// use the extra analysis (1) to filter trivial false positives or (2) to
7878 /// provide more context so that non-trivial false positives can be quickly
7979 /// detected by the user.
80 bool allowExtraAnalysis() const {
81 // For now, only allow this with -fsave-optimization-record since the -Rpass
82 // options are handled in the front-end.
83 return F->getContext().getDiagnosticsOutputFile();
80 bool allowExtraAnalysis(StringRef PassName) const {
81 return (F->getContext().getDiagnosticsOutputFile() ||
82 F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
8483 }
8584
8685 private:
7272
7373 /// \see DiagnosticInfoOptimizationBase::isEnabled.
7474 bool isEnabled() const override {
75 return OptimizationRemark::isEnabled(getPassName());
75 const Function &Fn = getFunction();
76 LLVMContext &Ctx = Fn.getContext();
77 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
7678 }
7779 };
7880
9698
9799 /// \see DiagnosticInfoOptimizationBase::isEnabled.
98100 bool isEnabled() const override {
99 return OptimizationRemarkMissed::isEnabled(getPassName());
101 const Function &Fn = getFunction();
102 LLVMContext &Ctx = Fn.getContext();
103 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
100104 }
101105 };
102106
120124
121125 /// \see DiagnosticInfoOptimizationBase::isEnabled.
122126 bool isEnabled() const override {
123 return OptimizationRemarkAnalysis::isEnabled(getPassName());
127 const Function &Fn = getFunction();
128 LLVMContext &Ctx = Fn.getContext();
129 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
124130 }
125131 };
126132
151157 /// that are normally too noisy. In this mode, we can use the extra analysis
152158 /// (1) to filter trivial false positives or (2) to provide more context so
153159 /// that non-trivial false positives can be quickly detected by the user.
154 bool allowExtraAnalysis() const {
155 // For now, only allow this with -fsave-optimization-record since the -Rpass
156 // options are handled in the front-end.
157 return MF.getFunction()->getContext().getDiagnosticsOutputFile();
160 bool allowExtraAnalysis(StringRef PassName) const {
161 return (MF.getFunction()->getContext().getDiagnosticsOutputFile() ||
162 MF.getFunction()->getContext()
163 .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
158164 }
159165
160166 private:
0 //===- DiagnosticHandler.h - DiagnosticHandler class for LLVM -*- C++ ---*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 // Base DiagnosticHandler class declaration. Derive from this class to provide
9 // custom diagnostic reporting.
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/ADT/StringRef.h"
13
14 namespace llvm {
15 class DiagnosticInfo;
16
17 /// \brief This is the base class for diagnostic handling in LLVM.
18 /// The handleDiagnostics method must be overriden by the subclasses to handle
19 /// diagnostic. The *RemarkEnabled methods can be overriden to control
20 /// which remarks are enabled.
21 struct DiagnosticHandler {
22 void *DiagnosticContext = nullptr;
23 DiagnosticHandler(void *DiagContext = nullptr)
24 : DiagnosticContext(DiagContext) {}
25 virtual ~DiagnosticHandler() = default;
26
27 using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context);
28
29 /// DiagHandlerCallback is settable from the C API and base implementation
30 /// of DiagnosticHandler will call it from handleDiagnostics(). Any derived
31 /// class of DiagnosticHandler should not use callback but
32 /// implement handleDiagnostics().
33 DiagnosticHandlerTy DiagHandlerCallback = nullptr;
34
35 /// Override handleDiagnostics to provide custom implementation.
36 /// Return true if it handles diagnostics reporting properly otherwise
37 /// return false to make LLVMContext::diagnose() to print the message
38 /// with a prefix based on the severity.
39 virtual bool handleDiagnostics(const DiagnosticInfo &DI) {
40 if (DiagHandlerCallback) {
41 DiagHandlerCallback(DI, DiagnosticContext);
42 return true;
43 }
44 return false;
45 }
46
47 /// Return true if analysis remarks are enabled, override
48 /// to provide different implementation.
49 virtual bool isAnalysisRemarkEnabled(StringRef PassName) const;
50
51 /// Return true if missed optimization remarks are enabled, override
52 /// to provide different implementation.
53 virtual bool isMissedOptRemarkEnabled(StringRef PassName) const;
54
55 /// Return true if passed optimization remarks are enabled, override
56 /// to provide different implementation.
57 virtual bool isPassedOptRemarkEnabled(StringRef PassName) const;
58
59 /// Return true if any type of remarks are enabled.
60 bool isAnyRemarkEnabled(StringRef PassName) const {
61 return (isMissedOptRemarkEnabled(PassName) ||
62 isPassedOptRemarkEnabled(PassName) ||
63 isAnalysisRemarkEnabled(PassName));
64 }
65 };
66 }
603603 return DI->getKind() == DK_OptimizationRemark;
604604 }
605605
606 static bool isEnabled(StringRef PassName);
607
608606 /// \see DiagnosticInfoOptimizationBase::isEnabled.
609 bool isEnabled() const override { return isEnabled(getPassName()); }
607 bool isEnabled() const override;
610608
611609 private:
612610 /// This is deprecated now and only used by the function API below.
646644 return DI->getKind() == DK_OptimizationRemarkMissed;
647645 }
648646
649 static bool isEnabled(StringRef PassName);
650
651647 /// \see DiagnosticInfoOptimizationBase::isEnabled.
652 bool isEnabled() const override { return isEnabled(getPassName()); }
648 bool isEnabled() const override;
653649
654650 private:
655651 /// This is deprecated now and only used by the function API below.
700696 return DI->getKind() == DK_OptimizationRemarkAnalysis;
701697 }
702698
703 static bool isEnabled(StringRef PassName);
704
705699 /// \see DiagnosticInfoOptimizationBase::isEnabled.
706 bool isEnabled() const override {
707 return shouldAlwaysPrint() || isEnabled(getPassName());
708 }
700 bool isEnabled() const override;
709701
710702 static const char *AlwaysPrint;
711703
1515 #define LLVM_IR_LLVMCONTEXT_H
1616
1717 #include "llvm-c/Types.h"
18 #include "llvm/IR/DiagnosticHandler.h"
1819 #include "llvm/Support/CBindingWrapping.h"
1920 #include "llvm/Support/Options.h"
2021 #include
166167 using InlineAsmDiagHandlerTy = void (*)(const SMDiagnostic&, void *Context,
167168 unsigned LocCookie);
168169
169 /// Defines the type of a diagnostic handler.
170 /// \see LLVMContext::setDiagnosticHandler.
171 /// \see LLVMContext::diagnose.
172 using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context);
173
174170 /// Defines the type of a yield callback.
175171 /// \see LLVMContext::setYieldCallback.
176172 using YieldCallbackTy = void (*)(LLVMContext *Context, void *OpaqueHandle);
193189 /// setInlineAsmDiagnosticHandler.
194190 void *getInlineAsmDiagnosticContext() const;
195191
196 /// setDiagnosticHandler - This method sets a handler that is invoked
197 /// when the backend needs to report anything to the user. The first
198 /// argument is a function pointer and the second is a context pointer that
199 /// gets passed into the DiagHandler. The third argument should be set to
192 /// setDiagnosticHandlerCallBack - This method sets a handler call back
193 /// that is invoked when the backend needs to report anything to the user.
194 /// The first argument is a function pointer and the second is a context pointer
195 /// that gets passed into the DiagHandler. The third argument should be set to
200196 /// true if the handler only expects enabled diagnostics.
201197 ///
202198 /// LLVMContext doesn't take ownership or interpret either of these
203199 /// pointers.
204 void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
205 void *DiagContext = nullptr,
200 void setDiagnosticHandlerCallBack(
201 DiagnosticHandler::DiagnosticHandlerTy DiagHandler,
202 void *DiagContext = nullptr, bool RespectFilters = false);
203
204 /// setDiagnosticHandler - This method sets unique_ptr to object of DiagnosticHandler
205 /// to provide custom diagnostic handling. The first argument is unique_ptr of object
206 /// of type DiagnosticHandler or a derived of that. The third argument should be
207 /// set to true if the handler only expects enabled diagnostics.
208 ///
209 /// Ownership of this pointer is moved to LLVMContextImpl.
210 void setDiagnosticHandler(std::unique_ptr &&DH,
206211 bool RespectFilters = false);
207212
208 /// getDiagnosticHandler - Return the diagnostic handler set by
209 /// setDiagnosticHandler.
210 DiagnosticHandlerTy getDiagnosticHandler() const;
213 /// getDiagnosticHandlerCallBack - Return the diagnostic handler call back set by
214 /// setDiagnosticHandlerCallBack.
215 DiagnosticHandler::DiagnosticHandlerTy getDiagnosticHandlerCallBack() const;
211216
212217 /// getDiagnosticContext - Return the diagnostic context set by
213218 /// setDiagnosticContext.
214219 void *getDiagnosticContext() const;
220
221 /// getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by
222 /// setDiagnosticHandler.
223 const DiagnosticHandler *getDiagHandlerPtr() const;
224
225 /// getDiagnosticHandler - transfers owenership of DiagnosticHandler unique_ptr
226 /// to caller.
227 std::unique_ptr getDiagnosticHandler();
215228
216229 /// \brief Return if a code hotness metric should be included in optimization
217230 /// diagnostics.
170170 bool UseInputModulePath = false);
171171 };
172172
173 struct LTOLLVMDiagnosticHandler : public DiagnosticHandler {
174 DiagnosticHandlerFunction *Fn;
175 LTOLLVMDiagnosticHandler(DiagnosticHandlerFunction *DiagHandlerFn)
176 : Fn(DiagHandlerFn) {}
177 bool handleDiagnostics(const DiagnosticInfo &DI) override {
178 (*Fn)(DI);
179 return true;
180 }
181 };
173182 /// A derived class of LLVMContext that initializes itself according to a given
174183 /// Config object. The purpose of this class is to tie ownership of the
175184 /// diagnostic handler to the context, as opposed to the Config object (which
176185 /// may be ephemeral).
186 // FIXME: This should not be required as diagnostic handler is not callback.
177187 struct LTOLLVMContext : LLVMContext {
178 static void funcDiagHandler(const DiagnosticInfo &DI, void *Context) {
179 auto *Fn = static_cast(Context);
180 (*Fn)(DI);
181 }
182188
183189 LTOLLVMContext(const Config &C) : DiagHandler(C.DiagHandler) {
184190 setDiscardValueNames(C.ShouldDiscardValueNames);
185191 enableDebugTypeODRUniquing();
186 setDiagnosticHandler(funcDiagHandler, &DiagHandler, true);
192 setDiagnosticHandler(
193 llvm::make_unique(&DiagHandler), true);
187194 }
188195 DiagnosticHandlerFunction DiagHandler;
189196 };
183183 LLVMContext &getContext() { return Context; }
184184
185185 void resetMergedModule() { MergedModule.reset(); }
186 void DiagnosticHandler(const DiagnosticInfo &DI);
186187
187188 private:
188189 void initializeLTOPasses();
202203
203204 bool determineTarget();
204205 std::unique_ptr createTargetMachine();
205
206 static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context);
207
208 void DiagnosticHandler2(const DiagnosticInfo &DI);
209206
210207 void emitError(const std::string &ErrMsg);
211208 void emitWarning(const std::string &ErrMsg);
1616 DebugInfo.cpp
1717 DebugInfoMetadata.cpp
1818 DebugLoc.cpp
19 DiagnosticHandler.cpp
1920 DiagnosticInfo.cpp
2021 DiagnosticPrinter.cpp
2122 Dominators.cpp
8484 void LLVMContextSetDiagnosticHandler(LLVMContextRef C,
8585 LLVMDiagnosticHandler Handler,
8686 void *DiagnosticContext) {
87 unwrap(C)->setDiagnosticHandler(
88 LLVM_EXTENSION reinterpret_cast(
87 unwrap(C)->setDiagnosticHandlerCallBack(
88 LLVM_EXTENSION reinterpret_cast(
8989 Handler),
9090 DiagnosticContext);
9191 }
9292
9393 LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C) {
9494 return LLVM_EXTENSION reinterpret_cast(
95 unwrap(C)->getDiagnosticHandler());
95 unwrap(C)->getDiagnosticHandlerCallBack());
9696 }
9797
9898 void *LLVMContextGetDiagnosticContext(LLVMContextRef C) {
0 //===- DiagnosticHandler.h - DiagnosticHandler class for LLVM -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //
10 //===----------------------------------------------------------------------===//
11 #include "llvm/IR/DiagnosticHandler.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/Support/Regex.h"
14
15 using namespace llvm;
16
17 namespace {
18
19 /// \brief Regular expression corresponding to the value given in one of the
20 /// -pass-remarks* command line flags. Passes whose name matches this regexp
21 /// will emit a diagnostic when calling the associated diagnostic function
22 /// (emitOptimizationRemark, emitOptimizationRemarkMissed or
23 /// emitOptimizationRemarkAnalysis).
24 struct PassRemarksOpt {
25 std::shared_ptr Pattern;
26
27 void operator=(const std::string &Val) {
28 // Create a regexp object to match pass names for emitOptimizationRemark.
29 if (!Val.empty()) {
30 Pattern = std::make_shared(Val);
31 std::string RegexError;
32 if (!Pattern->isValid(RegexError))
33 report_fatal_error("Invalid regular expression '" + Val +
34 "' in -pass-remarks: " + RegexError,
35 false);
36 }
37 }
38 };
39
40 static PassRemarksOpt PassRemarksPassedOptLoc;
41 static PassRemarksOpt PassRemarksMissedOptLoc;
42 static PassRemarksOpt PassRemarksAnalysisOptLoc;
43
44 // -pass-remarks
45 // Command line flag to enable emitOptimizationRemark()
46 static cl::opt> PassRemarks(
47 "pass-remarks", cl::value_desc("pattern"),
48 cl::desc("Enable optimization remarks from passes whose name match "
49 "the given regular expression"),
50 cl::Hidden, cl::location(PassRemarksPassedOptLoc), cl::ValueRequired,
51 cl::ZeroOrMore);
52
53 // -pass-remarks-missed
54 // Command line flag to enable emitOptimizationRemarkMissed()
55 static cl::opt> PassRemarksMissed(
56 "pass-remarks-missed", cl::value_desc("pattern"),
57 cl::desc("Enable missed optimization remarks from passes whose name match "
58 "the given regular expression"),
59 cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired,
60 cl::ZeroOrMore);
61
62 // -pass-remarks-analysis
63 // Command line flag to enable emitOptimizationRemarkAnalysis()
64 static cl::opt>
65 PassRemarksAnalysis(
66 "pass-remarks-analysis", cl::value_desc("pattern"),
67 cl::desc(
68 "Enable optimization analysis remarks from passes whose name match "
69 "the given regular expression"),
70 cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired,
71 cl::ZeroOrMore);
72 }
73
74 bool DiagnosticHandler::isAnalysisRemarkEnabled(StringRef PassName) const {
75 return (PassRemarksAnalysisOptLoc.Pattern &&
76 PassRemarksAnalysisOptLoc.Pattern->match(PassName));
77 }
78 bool DiagnosticHandler::isMissedOptRemarkEnabled(StringRef PassName) const {
79 return (PassRemarksMissedOptLoc.Pattern &&
80 PassRemarksMissedOptLoc.Pattern->match(PassName));
81 }
82 bool DiagnosticHandler::isPassedOptRemarkEnabled(StringRef PassName) const {
83 return (PassRemarksPassedOptLoc.Pattern &&
84 PassRemarksPassedOptLoc.Pattern->match(PassName));
85 }
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "llvm/IR/DiagnosticInfo.h"
15 #include "LLVMContextImpl.h"
1516 #include "llvm/ADT/StringExtras.h"
1617 #include "llvm/ADT/Twine.h"
1718 #include "llvm/ADT/iterator_range.h"
4041
4142 using namespace llvm;
4243
43 namespace {
44
45 /// \brief Regular expression corresponding to the value given in one of the
46 /// -pass-remarks* command line flags. Passes whose name matches this regexp
47 /// will emit a diagnostic via ORE->emit(...);
48 struct PassRemarksOpt {
49 std::shared_ptr Pattern;
50
51 void operator=(const std::string &Val) {
52 if (!Val.empty()) {
53 Pattern = std::make_shared(Val);
54 std::string RegexError;
55 if (!Pattern->isValid(RegexError))
56 report_fatal_error("Invalid regular expression '" + Val +
57 "' in -pass-remarks: " + RegexError,
58 false);
59 }
60 }
61 };
62
63 } // end anonymous namespace
64
65 static PassRemarksOpt PassRemarksOptLoc;
66 static PassRemarksOpt PassRemarksMissedOptLoc;
67 static PassRemarksOpt PassRemarksAnalysisOptLoc;
68
69 // -pass-remarks
70 // Command line flag to enable optimization remarks
71 static cl::opt>
72 PassRemarks("pass-remarks", cl::value_desc("pattern"),
73 cl::desc("Enable optimization remarks from passes whose name match "
74 "the given regular expression"),
75 cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired,
76 cl::ZeroOrMore);
77
78 // -pass-remarks-missed
79 // Command line flag to enable missed optimization remarks
80 static cl::opt> PassRemarksMissed(
81 "pass-remarks-missed", cl::value_desc("pattern"),
82 cl::desc("Enable missed optimization remarks from passes whose name match "
83 "the given regular expression"),
84 cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired,
85 cl::ZeroOrMore);
86
87 // -pass-remarks-analysis
88 // Command line flag to enable optimization analysis remarks
89 static cl::opt>
90 PassRemarksAnalysis(
91 "pass-remarks-analysis", cl::value_desc("pattern"),
92 cl::desc(
93 "Enable optimization analysis remarks from passes whose name match "
94 "the given regular expression"),
95 cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired,
96 cl::ZeroOrMore);
97
9844 int llvm::getNextAvailablePluginDiagnosticKind() {
9945 static std::atomic PluginKindID(DK_FirstPluginKind);
10046 return ++PluginKindID;
282228 RemarkName, *Func, Func->getSubprogram(),
283229 &getFirstFunctionBlock(Func)) {}
284230
285 bool OptimizationRemark::isEnabled(StringRef PassName) {
286 return PassRemarksOptLoc.Pattern &&
287 PassRemarksOptLoc.Pattern->match(PassName);
231 bool OptimizationRemark::isEnabled() const {
232 const Function &Fn = getFunction();
233 LLVMContext &Ctx = Fn.getContext();
234 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
288235 }
289236
290237 OptimizationRemarkMissed::OptimizationRemarkMissed(
302249 *Inst->getParent()->getParent(),
303250 Inst->getDebugLoc(), Inst->getParent()) {}
304251
305 bool OptimizationRemarkMissed::isEnabled(StringRef PassName) {
306 return PassRemarksMissedOptLoc.Pattern &&
307 PassRemarksMissedOptLoc.Pattern->match(PassName);
252 bool OptimizationRemarkMissed::isEnabled() const {
253 const Function &Fn = getFunction();
254 LLVMContext &Ctx = Fn.getContext();
255 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
308256 }
309257
310258 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
329277 *cast(CodeRegion)->getParent(),
330278 Loc, CodeRegion) {}
331279
332 bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) {
333 return PassRemarksAnalysisOptLoc.Pattern &&
334 PassRemarksAnalysisOptLoc.Pattern->match(PassName);
280 bool OptimizationRemarkAnalysis::isEnabled() const {
281 const Function &Fn = getFunction();
282 LLVMContext &Ctx = Fn.getContext();
283 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||
284 shouldAlwaysPrint();
335285 }
336286
337287 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
128128 return pImpl->InlineAsmDiagContext;
129129 }
130130
131 void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
132 void *DiagnosticContext,
133 bool RespectFilters) {
134 pImpl->DiagnosticHandler = DiagnosticHandler;
135 pImpl->DiagnosticContext = DiagnosticContext;
131 void LLVMContext::setDiagnosticHandlerCallBack(
132 DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler,
133 void *DiagnosticContext, bool RespectFilters) {
134 pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler;
135 pImpl->DiagHandler->DiagnosticContext = DiagnosticContext;
136 pImpl->RespectDiagnosticFilters = RespectFilters;
137 }
138
139 void LLVMContext::setDiagnosticHandler(std::unique_ptr &&DH,
140 bool RespectFilters) {
141 pImpl->DiagHandler = std::move(DH);
136142 pImpl->RespectDiagnosticFilters = RespectFilters;
137143 }
138144
158164 pImpl->DiagnosticsOutputFile = std::move(F);
159165 }
160166
161 LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
162 return pImpl->DiagnosticHandler;
167 DiagnosticHandler::DiagnosticHandlerTy
168 LLVMContext::getDiagnosticHandlerCallBack() const {
169 return pImpl->DiagHandler->DiagHandlerCallback;
163170 }
164171
165172 void *LLVMContext::getDiagnosticContext() const {
166 return pImpl->DiagnosticContext;
173 return pImpl->DiagHandler->DiagnosticContext;
167174 }
168175
169176 void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)
214221
215222 void LLVMContext::diagnose(const DiagnosticInfo &DI) {
216223 // If there is a report handler, use it.
217 if (pImpl->DiagnosticHandler) {
218 if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI))
219 pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
224 if (pImpl->DiagHandler &&
225 (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) &&
226 pImpl->DiagHandler->handleDiagnostics(DI))
220227 return;
221 }
222228
223229 if (!isDiagnosticEnabled(DI))
224230 return;
314320 OptBisect &LLVMContext::getOptBisect() {
315321 return pImpl->getOptBisect();
316322 }
323
324 const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {
325 return pImpl->DiagHandler.get();
326 }
327
328 std::unique_ptr LLVMContext::getDiagnosticHandler() {
329 return std::move(pImpl->DiagHandler);
330 }
2121 using namespace llvm;
2222
2323 LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
24 : VoidTy(C, Type::VoidTyID),
24 : DiagHandler(llvm::make_unique()),
25 VoidTy(C, Type::VoidTyID),
2526 LabelTy(C, Type::LabelTyID),
2627 HalfTy(C, Type::HalfTyID),
2728 FloatTy(C, Type::FloatTyID),
11671167 LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr;
11681168 void *InlineAsmDiagContext = nullptr;
11691169
1170 LLVMContext::DiagnosticHandlerTy DiagnosticHandler = nullptr;
1171 void *DiagnosticContext = nullptr;
1170 std::unique_ptr DiagHandler;
11721171 bool RespectDiagnosticFilters = false;
11731172 bool DiagnosticsHotnessRequested = false;
11741173 uint64_t DiagnosticsHotnessThreshold = 0;
621621 }
622622 }
623623
624 void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,
625 void *Context) {
626 ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI);
627 }
628
629 void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
624
625 void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI) {
630626 // Map the LLVM internal diagnostic severity to the LTO diagnostic severity.
631627 lto_codegen_diagnostic_severity_t Severity;
632628 switch (DI.getSeverity()) {
656652 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
657653 }
658654
655 namespace {
656 struct LTODiagnosticHandler : public DiagnosticHandler {
657 LTOCodeGenerator *CodeGenerator;
658 LTODiagnosticHandler(LTOCodeGenerator *CodeGenPtr)
659 : CodeGenerator(CodeGenPtr) {}
660 bool handleDiagnostics(const DiagnosticInfo &DI) override {
661 CodeGenerator->DiagnosticHandler(DI);
662 return true;
663 }
664 };
665 }
666
659667 void
660668 LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
661669 void *Ctxt) {
662670 this->DiagHandler = DiagHandler;
663671 this->DiagContext = Ctxt;
664672 if (!DiagHandler)
665 return Context.setDiagnosticHandler(nullptr, nullptr);
673 return Context.setDiagnosticHandler(nullptr);
666674 // Register the LTOCodeGenerator stub in the LLVMContext to forward the
667675 // diagnostic to the external DiagHandler.
668 Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this,
669 /* RespectFilters */ true);
676 Context.setDiagnosticHandler(llvm::make_unique(this),
677 true);
670678 }
671679
672680 namespace {
919919 Instruction *I = DepInfo.getInst();
920920 dbgs() << " is clobbered by " << *I << '\n';
921921 );
922
923 if (ORE->allowExtraAnalysis())
922 if (ORE->allowExtraAnalysis(DEBUG_TYPE))
924923 reportMayClobberedLoad(LI, DepInfo, DT, ORE);
925924
926925 return false;
49564956 // Store the result and return it at the end instead of exiting early, in case
49574957 // allowExtraAnalysis is used to report multiple reasons for not vectorizing.
49584958 bool Result = true;
4959
4960 bool DoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE);
4961 if (DoExtraAnalysis)
49594962 // We must have a loop in canonical form. Loops with indirectbr in them cannot
49604963 // be canonicalized.
49614964 if (!TheLoop->getLoopPreheader()) {
49624965 ORE->emit(createMissedAnalysis("CFGNotUnderstood")
49634966 << "loop control flow is not understood by vectorizer");
4964 if (ORE->allowExtraAnalysis())
4967 if (DoExtraAnalysis)
49654968 Result = false;
49664969 else
49674970 return false;
49744977 if (!TheLoop->empty()) {
49754978 ORE->emit(createMissedAnalysis("NotInnermostLoop")
49764979 << "loop is not the innermost loop");
4977 if (ORE->allowExtraAnalysis())
4980 if (DoExtraAnalysis)
49784981 Result = false;
49794982 else
49804983 return false;
49844987 if (TheLoop->getNumBackEdges() != 1) {
49854988 ORE->emit(createMissedAnalysis("CFGNotUnderstood")
49864989 << "loop control flow is not understood by vectorizer");
4987 if (ORE->allowExtraAnalysis())
4990 if (DoExtraAnalysis)
49884991 Result = false;
49894992 else
49904993 return false;
49944997 if (!TheLoop->getExitingBlock()) {
49954998 ORE->emit(createMissedAnalysis("CFGNotUnderstood")
49964999 << "loop control flow is not understood by vectorizer");
4997 if (ORE->allowExtraAnalysis())
5000 if (DoExtraAnalysis)
49985001 Result = false;
49995002 else
50005003 return false;
50065009 if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) {
50075010 ORE->emit(createMissedAnalysis("CFGNotUnderstood")
50085011 << "loop control flow is not understood by vectorizer");
5009 if (ORE->allowExtraAnalysis())
5012 if (DoExtraAnalysis)
50105013 Result = false;
50115014 else
50125015 return false;
50205023 unsigned NumBlocks = TheLoop->getNumBlocks();
50215024 if (NumBlocks != 1 && !canVectorizeWithIfConvert()) {
50225025 DEBUG(dbgs() << "LV: Can't if-convert the loop.\n");
5023 if (ORE->allowExtraAnalysis())
5026 if (DoExtraAnalysis)
50245027 Result = false;
50255028 else
50265029 return false;
50295032 // Check if we can vectorize the instructions and CFG in this loop.
50305033 if (!canVectorizeInstrs()) {
50315034 DEBUG(dbgs() << "LV: Can't vectorize the instructions or CFG\n");
5032 if (ORE->allowExtraAnalysis())
5035 if (DoExtraAnalysis)
50335036 Result = false;
50345037 else
50355038 return false;
50385041 // Go over each instruction and look at memory deps.
50395042 if (!canVectorizeMemory()) {
50405043 DEBUG(dbgs() << "LV: Can't vectorize due to memory conflicts\n");
5041 if (ORE->allowExtraAnalysis())
5044 if (DoExtraAnalysis)
50425045 Result = false;
50435046 else
50445047 return false;
50695072 << "Too many SCEV assumptions need to be made and checked "
50705073 << "at runtime");
50715074 DEBUG(dbgs() << "LV: Too many SCEV checks needed.\n");
5072 if (ORE->allowExtraAnalysis())
5075 if (DoExtraAnalysis)
50735076 Result = false;
50745077 else
50755078 return false;
1010 ; CHECK: remark: :0:0: load of type i32 eliminated{{$}}
1111 ; CHECK-NEXT: remark: :0:0: load of type i32 eliminated{{$}}
1212 ; CHECK-NEXT: remark: :0:0: load of type i32 eliminated{{$}}
13 ; CHECK-NOT: remark:
13 ; CHECK-NEXT: remark: /tmp/s.c:3:3: load of type i32 not eliminated
1414
1515 ; YAML: --- !Passed
1616 ; YAML-NEXT: Pass: gvn
234234 return FDOut;
235235 }
236236
237 static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) {
238 bool *HasError = static_cast(Context);
239 if (DI.getSeverity() == DS_Error)
240 *HasError = true;
241
242 if (auto *Remark = dyn_cast(&DI))
243 if (!Remark->isEnabled())
244 return;
245
246 DiagnosticPrinterRawOStream DP(errs());
247 errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
248 DI.print(DP);
249 errs() << "\n";
250 }
237 struct LLCDiagnosticHandler : public DiagnosticHandler {
238 bool *HasError;
239 LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {}
240 bool handleDiagnostics(const DiagnosticInfo &DI) override {
241 if (DI.getSeverity() == DS_Error)
242 *HasError = true;
243
244 if (auto *Remark = dyn_cast(&DI))
245 if (!Remark->isEnabled())
246 return true;
247
248 DiagnosticPrinterRawOStream DP(errs());
249 errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
250 DI.print(DP);
251 errs() << "\n";
252 return true;
253 }
254 };
251255
252256 static void InlineAsmDiagHandler(const SMDiagnostic &SMD, void *Context,
253257 unsigned LocCookie) {
307311
308312 // Set a diagnostic handler that doesn't exit on the first error
309313 bool HasError = false;
310 Context.setDiagnosticHandler(DiagnosticHandler, &HasError);
314 Context.setDiagnosticHandler(
315 llvm::make_unique(&HasError));
311316 Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError);
312317
313318 if (PassRemarksWithHotness)
563568
564569 PM.run(*M);
565570
566 auto HasError = *static_cast(Context.getDiagnosticContext());
567 if (HasError)
571 auto HasError =
572 ((const LLCDiagnosticHandler *)(Context.getDiagHandlerPtr()))->HasError;
573 if (*HasError)
568574 return 1;
569575
570576 // Compare the two outputs and make sure they're the same
121121 }
122122 };
123123
124 struct LLVMDisDiagnosticHandler : public DiagnosticHandler {
125 char *Prefix;
126 LLVMDisDiagnosticHandler(char *PrefixPtr) : Prefix(PrefixPtr) {}
127 bool handleDiagnostics(const DiagnosticInfo &DI) override {
128 raw_ostream &OS = errs();
129 OS << Prefix << ": ";
130 switch (DI.getSeverity()) {
131 case DS_Error: OS << "error: "; break;
132 case DS_Warning: OS << "warning: "; break;
133 case DS_Remark: OS << "remark: "; break;
134 case DS_Note: OS << "note: "; break;
135 }
136
137 DiagnosticPrinterRawOStream DP(OS);
138 DI.print(DP);
139 OS << '\n';
140
141 if (DI.getSeverity() == DS_Error)
142 exit(1);
143 return true;
144 }
145 };
124146 } // end anon namespace
125
126 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
127 raw_ostream &OS = errs();
128 OS << (char *)Context << ": ";
129 switch (DI.getSeverity()) {
130 case DS_Error: OS << "error: "; break;
131 case DS_Warning: OS << "warning: "; break;
132 case DS_Remark: OS << "remark: "; break;
133 case DS_Note: OS << "note: "; break;
134 }
135
136 DiagnosticPrinterRawOStream DP(OS);
137 DI.print(DP);
138 OS << '\n';
139
140 if (DI.getSeverity() == DS_Error)
141 exit(1);
142 }
143147
144148 static ExitOnError ExitOnErr;
145149
165169
166170 LLVMContext Context;
167171 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
168
169 Context.setDiagnosticHandler(diagnosticHandler, argv[0]);
170
172 Context.setDiagnosticHandler(
173 llvm::make_unique(argv[0]));
171174 cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n");
172175
173176 std::unique_ptr M = openInputFile(Context);
181181 }
182182 } // anonymous namespace
183183
184 static void diagnosticHandler(const DiagnosticInfo &DI, void *C) {
185 unsigned Severity = DI.getSeverity();
186 switch (Severity) {
187 case DS_Error:
188 errs() << "ERROR: ";
189 break;
190 case DS_Warning:
191 if (SuppressWarnings)
192 return;
193 errs() << "WARNING: ";
194 break;
195 case DS_Remark:
196 case DS_Note:
197 llvm_unreachable("Only expecting warnings and errors");
198 }
199
200 DiagnosticPrinterRawOStream DP(errs());
201 DI.print(DP);
202 errs() << '\n';
184 namespace {
185 struct LLVMLinkDiagnosticHandler : public DiagnosticHandler {
186 bool handleDiagnostics(const DiagnosticInfo &DI) override {
187 unsigned Severity = DI.getSeverity();
188 switch (Severity) {
189 case DS_Error:
190 errs() << "ERROR: ";
191 break;
192 case DS_Warning:
193 if (SuppressWarnings)
194 return true;
195 errs() << "WARNING: ";
196 break;
197 case DS_Remark:
198 case DS_Note:
199 llvm_unreachable("Only expecting warnings and errors");
200 }
201
202 DiagnosticPrinterRawOStream DP(errs());
203 DI.print(DP);
204 errs() << '\n';
205 return true;
206 }
207 };
203208 }
204209
205210 /// Import any functions requested via the -import option.
346351 ExitOnErr.setBanner(std::string(argv[0]) + ": ");
347352
348353 LLVMContext Context;
349 Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);
350
354 Context.setDiagnosticHandler(
355 llvm::make_unique(), true);
351356 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
352357 cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
353358
234234 }
235235
236236 static std::string CurrentActivity;
237 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
238 raw_ostream &OS = errs();
239 OS << "llvm-lto: ";
240 switch (DI.getSeverity()) {
241 case DS_Error:
242 OS << "error";
243 break;
244 case DS_Warning:
245 OS << "warning";
246 break;
247 case DS_Remark:
248 OS << "remark";
249 break;
250 case DS_Note:
251 OS << "note";
252 break;
253 }
254 if (!CurrentActivity.empty())
255 OS << ' ' << CurrentActivity;
256 OS << ": ";
257
258 DiagnosticPrinterRawOStream DP(OS);
259 DI.print(DP);
260 OS << '\n';
261
262 if (DI.getSeverity() == DS_Error)
263 exit(1);
264 }
237
238 namespace {
239 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
240 bool handleDiagnostics(const DiagnosticInfo &DI) override {
241 raw_ostream &OS = errs();
242 OS << "llvm-lto: ";
243 switch (DI.getSeverity()) {
244 case DS_Error:
245 OS << "error";
246 break;
247 case DS_Warning:
248 OS << "warning";
249 break;
250 case DS_Remark:
251 OS << "remark";
252 break;
253 case DS_Note:
254 OS << "note";
255 break;
256 }
257 if (!CurrentActivity.empty())
258 OS << ' ' << CurrentActivity;
259 OS << ": ";
260
261 DiagnosticPrinterRawOStream DP(OS);
262 DI.print(DP);
263 OS << '\n';
264
265 if (DI.getSeverity() == DS_Error)
266 exit(1);
267 return true;
268 }
269 };
270 }
265271
266272 static void error(const Twine &Msg) {
267273 errs() << "llvm-lto: " << Msg << '\n';
292298 Buffer = std::move(BufferOrErr.get());
293299 CurrentActivity = ("loading file '" + Path + "'").str();
294300 std::unique_ptr Context = llvm::make_unique();
295 Context->setDiagnosticHandler(diagnosticHandler, nullptr, true);
301 Context->setDiagnosticHandler(llvm::make_unique(),
302 true);
296303 ErrorOr> Ret = LTOModule::createInLocalContext(
297304 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
298305 Options, Path);
836843 unsigned BaseArg = 0;
837844
838845 LLVMContext Context;
839 Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);
846 Context.setDiagnosticHandler(llvm::make_unique(),
847 true);
840848
841849 LTOCodeGenerator CodeGen(Context);
842850
7474
7575 static LLVMContext *LTOContext = nullptr;
7676
77 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
78 if (DI.getSeverity() != DS_Error) {
79 DiagnosticPrinterRawOStream DP(errs());
80 DI.print(DP);
81 errs() << '\n';
82 return;
83 }
84 sLastErrorString = "";
85 {
86 raw_string_ostream Stream(sLastErrorString);
87 DiagnosticPrinterRawOStream DP(Stream);
88 DI.print(DP);
89 }
90 }
77 struct LTOToolDiagnosticHandler : public DiagnosticHandler {
78 bool handleDiagnostics(const DiagnosticInfo &DI) override {
79 if (DI.getSeverity() != DS_Error) {
80 DiagnosticPrinterRawOStream DP(errs());
81 DI.print(DP);
82 errs() << '\n';
83 return true;
84 }
85 sLastErrorString = "";
86 {
87 raw_string_ostream Stream(sLastErrorString);
88 DiagnosticPrinterRawOStream DP(Stream);
89 DI.print(DP);
90 }
91 return true;
92 }
93 };
9194
9295 // Initialize the configured targets if they have not been initialized.
9396 static void lto_initialize() {
107110
108111 static LLVMContext Context;
109112 LTOContext = &Context;
110 LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true);
113 LTOContext->setDiagnosticHandler(
114 llvm::make_unique(), true);
111115 initialized = true;
112116 }
113117 }
273277
274278 // Create a local context. Ownership will be transferred to LTOModule.
275279 std::unique_ptr Context = llvm::make_unique();
276 Context->setDiagnosticHandler(diagnosticHandler, nullptr, true);
280 Context->setDiagnosticHandler(llvm::make_unique(),
281 true);
277282
278283 ErrorOr> M = LTOModule::createInLocalContext(
279284 std::move(Context), mem, length, Options, StringRef(path));