1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "common/debug/Debug.hpp"
10 
11 #include "common/debug/TeeOutputStream.hpp"
12 
13 #include "AdaptorCommon/customApi.hpp"
14 
15 #include "common/LLVMWarningsPush.hpp"
16 #include "llvm/Config/llvm-config.h"
17 #include "llvm/IR/DiagnosticInfo.h"
18 #include "llvm/IR/DiagnosticPrinter.h"
19 #include "llvm/IR/LLVMContext.h"
20 #include "llvm/IR/Value.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/FormattedStream.h"
26 #include "llvm/Support/ManagedStatic.h"
27 #include "llvm/Support/SourceMgr.h"
28 #include "common/LLVMWarningsPop.hpp"
29 
30 #if defined( _WIN32 ) || defined( _WIN64 )
31 #   include <io.h>
32 #   include <windows.h>
33 // Windows.h defines MemoryFence as _mm_mfence, but this conflicts with llvm::sys::MemoryFence
34 #undef MemoryFence
35 #endif
36 #include <sstream>
37 #include <string>
38 #include <exception>
39 #include <stdexcept>
40 #include <mutex>
41 #include "Probe/Assertion.h"
42 
43 using namespace llvm;
44 
45 #if defined _WIN32 || _WIN64
46 //#if defined( _DEBUG )
47 #include "psapi.h"
48 
49 #ifdef IGC_METRICS__PROTOBUF_ATTACHED
50 #include <google/protobuf/message_lite.h>
51 #endif
52 
CatchAssert(int reportType,char * userMessage,int * retVal)53 int CatchAssert( int reportType, char *userMessage, int *retVal )
54 {
55     IGC_ASSERT(0);
56     if(IsDebuggerPresent())
57     {
58         *retVal = 1; // Break into the debugger or print a stack
59     }
60     else
61     {
62         *retVal = 0;
63     }
64     return true; // we always want to abort, return false pops up a window
65 }
66 
DllMain(_In_ HINSTANCE hinstDLL,_In_ DWORD fdwReason,_In_ LPVOID lpvReserved)67 BOOL WINAPI DllMain(
68     _In_  HINSTANCE hinstDLL,
69     _In_  DWORD fdwReason,
70     _In_  LPVOID lpvReserved
71 )
72 {
73 
74     _CrtSetReportHook(CatchAssert);
75     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
76     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
77     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
78     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
79     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
80     _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
81     _set_error_mode(_OUT_TO_STDERR);
82 
83     switch(fdwReason) {
84     case DLL_PROCESS_DETACH:
85         llvm_shutdown();
86 
87 #ifdef IGC_METRICS__PROTOBUF_ATTACHED
88         // Optional:  Delete all global objects allocated by libprotobuf.
89         google::protobuf::ShutdownProtobufLibrary();
90 #endif
91         break;
92 
93     case DLL_PROCESS_ATTACH:
94         break;
95 
96     case DLL_THREAD_DETACH:
97         break;
98 
99     case DLL_THREAD_ATTACH:
100         break;
101     }
102     return TRUE;
103 }
104 #endif
105 
106 namespace IGC
107 {
108 namespace Debug
109 {
110 
111 #if defined _WIN32 || WIN64
112 namespace
113 {
114     class DebugOutputStream
115         : public raw_ostream
116     {
117     public:
DebugOutputStream()118         DebugOutputStream()
119             : raw_ostream( true /* unbuffered */ )
120         {
121         }
122 
~DebugOutputStream()123         ~DebugOutputStream()
124         {
125             flush();
126         }
127 
has_colors()128         bool has_colors()
129         {
130             return false;
131         }
132 
is_displayed()133         bool is_displayed()
134         {
135             return true;
136         }
137 
current_pos() const138         virtual uint64_t current_pos() const
139         {
140             return 0;
141         }
142 
preferred_buffer_size() const143         size_t preferred_buffer_size() const
144         {
145             return 0;
146         }
147 
148     private:
write_impl(const char * Ptr,size_t Size)149         virtual void write_impl(const char* Ptr, size_t Size)
150         {
151             std::stringstream ss;
152             ss.write(Ptr, Size);
153             OutputDebugStringA(ss.str().c_str());
154         }
155     };
156 } // end anonymous namespace
157 #endif
158 
Banner(raw_ostream & OS,std::string const & message)159 void Banner(raw_ostream & OS, std::string const& message)
160 {
161 #if _DEBUG
162     if ( GetDebugFlag(DebugFlag::DUMPS) )
163     {
164         OS.changeColor( raw_ostream::YELLOW, true, false );
165         OS << "-----------------------------------------\n";
166         OS << message << "\n";
167         OS << "-----------------------------------------\n";
168         OS.resetColor();
169     }
170 #endif
171 }
172 
ods()173 raw_ostream &ods()
174 {
175 #if defined( _DEBUG ) || defined( _INTERNAL )
176     if ( IGC_IS_FLAG_ENABLED(PrintToConsole) )
177     {
178 #    if defined _WIN32 || WIN64
179         {
180             static DebugOutputStream dos;
181             static TeeOutputStream tee( errs(), dos );
182             if ( GetDebugFlag(DebugFlag::DUMP_TO_OUTS) )
183             {
184                 return tee;
185             }
186             else
187             {
188                 return dos;
189             }
190         }
191 #    else
192         {
193             if ( GetDebugFlag(DebugFlag::DUMP_TO_OUTS) )
194             {
195                 return outs();
196             }
197             else
198             {
199                 return nulls();
200             }
201         }
202 #    endif
203     }
204     else
205 #endif
206     {
207         return nulls();
208     }
209 }
210 
211 
Warning(const char * pExpr,unsigned int line,const char * pFileName,std::string const & message)212 void Warning(
213     const char*           pExpr,
214     unsigned int          line,
215     const char*           pFileName,
216     std::string    const& message )
217 {
218 #if _DEBUG
219     if ( GetDebugFlag(DebugFlag::DUMPS) )
220     {
221         ods().changeColor( raw_ostream::MAGENTA, true, false );
222         ods() << pFileName << "(" << line << ") : ";
223         ods() << "IGC Warning: (" << pExpr << ") " << message << "\n";
224         ods().resetColor();
225         ods().flush();
226     }
227 #endif
228 }
229 
230 namespace {
FatalErrorHandler(void * user_data,const std::string & reason,bool gen_crash_diag)231     void FatalErrorHandler(void *user_data, const std::string& reason, bool gen_crash_diag)
232     {
233         (void)user_data;
234         (void)reason;
235 #if defined( _DEBUG )
236 #if defined( _WIN32 )
237         OutputDebugStringA("LLVM Error: ");
238         OutputDebugStringA(reason.c_str());
239         OutputDebugStringA("\n");
240 #endif
241         fprintf( stderr, "%s", "LLVM Error: " );
242         fprintf( stderr, "%s", reason.c_str());
243         fprintf( stderr, "%s", "\n");
244         fflush( stderr );
245 
246         if ( reason != "IO failure on output stream." )
247         {
248             exit(1);
249         }
250 #endif
251     }
252 
ComputeFatalErrorHandler(const DiagnosticInfo & DI,void *)253     void ComputeFatalErrorHandler(const DiagnosticInfo &DI, void * /*Context*/) {
254         // Skip non-error diag.
255         if (DI.getSeverity() != DS_Error)
256             return;
257         std::string MsgStorage;
258         raw_string_ostream Stream(MsgStorage);
259         DiagnosticPrinterRawOStream DP(Stream);
260         DI.print(DP);
261         Stream.flush();
262 
263         std::string msg;
264         msg += "\nerror: ";
265         msg += MsgStorage;
266         msg += "\nerror: backend compiler failed build.\n";
267     }
268 }
269 
RegisterErrHandlers()270 void RegisterErrHandlers()
271 {
272     static bool executed = false;
273     if (!executed)
274     {
275         install_fatal_error_handler( FatalErrorHandler, nullptr );
276         executed = true;
277     }
278 }
279 
RegisterComputeErrHandlers(LLVMContext & C)280 void RegisterComputeErrHandlers(LLVMContext &C)
281 {
282 #if LLVM_VERSION_MAJOR == 4
283     C.setDiagnosticHandler(ComputeFatalErrorHandler);
284 #elif LLVM_VERSION_MAJOR >= 7
285     C.setDiagnosticHandlerCallBack(ComputeFatalErrorHandler);
286 #endif
287 }
288 
ReleaseErrHandlers()289 void ReleaseErrHandlers()
290 {
291     // do nothing
292 }
293 
294 static std::mutex stream_mutex;
295 
DumpLock()296 void DumpLock()
297 {
298     stream_mutex.lock();
299 }
300 
DumpUnlock()301 void DumpUnlock()
302 {
303     stream_mutex.unlock();
304 }
305 
306 } // namespace Debug
307 
getPointerSize(llvm::Module & M)308 int getPointerSize(llvm::Module &M) {
309     return M.getDataLayout().getPointerSize();
310 }
311 
312 } // namespace IGC
313