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