@@ -23,6 +23,7 @@ use rustc_middle::bug;
2323use rustc_middle:: ty:: TyCtxt ;
2424use rustc_session:: config:: { self , Lto , OutputType , Passes , Sanitizer , SwitchWithOptPath } ;
2525use rustc_session:: Session ;
26+ use rustc_span:: InnerSpan ;
2627use rustc_target:: spec:: { CodeModel , RelocModel } ;
2728
2829use libc:: { c_char, c_int, c_uint, c_void, size_t} ;
@@ -238,12 +239,19 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
238239 }
239240}
240241
241- unsafe extern "C" fn report_inline_asm (
242+ fn report_inline_asm (
242243 cgcx : & CodegenContext < LlvmCodegenBackend > ,
243- msg : & str ,
244- cookie : c_uint ,
244+ msg : String ,
245+ mut cookie : c_uint ,
246+ source : Option < ( String , Vec < InnerSpan > ) > ,
245247) {
246- cgcx. diag_emitter . inline_asm_error ( cookie as u32 , msg. to_owned ( ) ) ;
248+ // In LTO build we may get srcloc values from other crates which are invalid
249+ // since they use a different source map. To be safe we just suppress these
250+ // in LTO builds.
251+ if matches ! ( cgcx. lto, Lto :: Fat | Lto :: Thin ) {
252+ cookie = 0 ;
253+ }
254+ cgcx. diag_emitter . inline_asm_error ( cookie as u32 , msg, source) ;
247255}
248256
249257unsafe extern "C" fn inline_asm_handler ( diag : & SMDiagnostic , user : * const c_void , cookie : c_uint ) {
@@ -252,10 +260,37 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
252260 }
253261 let ( cgcx, _) = * ( user as * const ( & CodegenContext < LlvmCodegenBackend > , & Handler ) ) ;
254262
255- let msg = llvm:: build_string ( |s| llvm:: LLVMRustWriteSMDiagnosticToString ( diag, s) )
256- . expect ( "non-UTF8 SMDiagnostic" ) ;
263+ // Recover the post-substitution assembly code from LLVM for better
264+ // diagnostics.
265+ let mut have_source = false ;
266+ let mut buffer = String :: new ( ) ;
267+ let mut loc = 0 ;
268+ let mut ranges = [ 0 ; 8 ] ;
269+ let mut num_ranges = ranges. len ( ) / 2 ;
270+ let msg = llvm:: build_string ( |msg| {
271+ buffer = llvm:: build_string ( |buffer| {
272+ have_source = llvm:: LLVMRustUnpackSMDiagnostic (
273+ diag,
274+ msg,
275+ buffer,
276+ & mut loc,
277+ ranges. as_mut_ptr ( ) ,
278+ & mut num_ranges,
279+ ) ;
280+ } )
281+ . expect ( "non-UTF8 inline asm" ) ;
282+ } )
283+ . expect ( "non-UTF8 SMDiagnostic" ) ;
284+
285+ let source = have_source. then ( || {
286+ let mut spans = vec ! [ InnerSpan :: new( loc as usize , loc as usize ) ] ;
287+ for i in 0 ..num_ranges {
288+ spans. push ( InnerSpan :: new ( ranges[ i * 2 ] as usize , ranges[ i * 2 + 1 ] as usize ) ) ;
289+ }
290+ ( buffer, spans)
291+ } ) ;
257292
258- report_inline_asm ( cgcx, & msg, cookie) ;
293+ report_inline_asm ( cgcx, msg, cookie, source ) ;
259294}
260295
261296unsafe extern "C" fn diagnostic_handler ( info : & DiagnosticInfo , user : * mut c_void ) {
@@ -266,7 +301,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
266301
267302 match llvm:: diagnostic:: Diagnostic :: unpack ( info) {
268303 llvm:: diagnostic:: InlineAsm ( inline) => {
269- report_inline_asm ( cgcx, & llvm:: twine_to_string ( inline. message ) , inline. cookie ) ;
304+ report_inline_asm ( cgcx, llvm:: twine_to_string ( inline. message ) , inline. cookie , None ) ;
270305 }
271306
272307 llvm:: diagnostic:: Optimization ( opt) => {
0 commit comments