1use inkwell::{
2 context::{AsContextRef, Context},
3 llvm_sys::{core::*, prelude::*, LLVMDiagnosticHandler, LLVMDiagnosticSeverity::*},
4};
5use std::{ffi::c_void, fmt, ptr};
6
7pub(crate) struct DiagnosticHandlerGuard<'ctx> {
9 cx: &'ctx Context,
10 prev_dh: LLVMDiagnosticHandler,
11 prev_dhc: *mut c_void,
12}
13
14impl fmt::Debug for DiagnosticHandlerGuard<'_> {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 f.debug_struct("DiagnosticHandlerGuard").finish_non_exhaustive()
17 }
18}
19
20impl<'ctx> DiagnosticHandlerGuard<'ctx> {
21 pub(crate) fn new(cx: &'ctx Context) -> Self {
22 unsafe {
23 let c = cx.as_ctx_ref();
24 let prev_dh = LLVMContextGetDiagnosticHandler(c);
25 let prev_dhc = LLVMContextGetDiagnosticContext(c);
26 LLVMContextSetDiagnosticHandler(c, Some(Self::diagnostic_handler), ptr::null_mut());
27 Self { cx, prev_dh, prev_dhc }
28 }
29 }
30
31 extern "C" fn diagnostic_handler(di: LLVMDiagnosticInfoRef, _context: *mut c_void) {
32 unsafe {
33 let msg_cstr = crate::llvm_string(LLVMGetDiagInfoDescription(di));
35 let msg = msg_cstr.to_string_lossy();
36 match LLVMGetDiagInfoSeverity(di) {
37 LLVMDSError => error!(target: "llvm", "{msg}"),
38 LLVMDSWarning => warn!(target: "llvm", "{msg}"),
39 LLVMDSRemark => trace!(target: "llvm", "{msg}"),
40 LLVMDSNote => debug!(target: "llvm", "{msg}"),
41 }
42 }
43 }
44}
45
46impl Drop for DiagnosticHandlerGuard<'_> {
47 fn drop(&mut self) {
48 unsafe {
49 LLVMContextSetDiagnosticHandler(self.cx.as_ctx_ref(), self.prev_dh, self.prev_dhc);
50 }
51 }
52}