@@ -23,6 +23,7 @@ use rustc_middle::bug;
23
23
use rustc_middle:: ty:: TyCtxt ;
24
24
use rustc_session:: config:: { self , Lto , OutputType , Passes , Sanitizer , SwitchWithOptPath } ;
25
25
use rustc_session:: Session ;
26
+ use rustc_span:: InnerSpan ;
26
27
use rustc_target:: spec:: { CodeModel , RelocModel } ;
27
28
28
29
use libc:: { c_char, c_int, c_uint, c_void, size_t} ;
@@ -238,12 +239,19 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
238
239
}
239
240
}
240
241
241
- unsafe extern "C" fn report_inline_asm (
242
+ fn report_inline_asm (
242
243
cgcx : & CodegenContext < LlvmCodegenBackend > ,
243
- msg : & str ,
244
- cookie : c_uint ,
244
+ msg : String ,
245
+ mut cookie : c_uint ,
246
+ source : Option < ( String , Vec < InnerSpan > ) > ,
245
247
) {
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) ;
247
255
}
248
256
249
257
unsafe 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
252
260
}
253
261
let ( cgcx, _) = * ( user as * const ( & CodegenContext < LlvmCodegenBackend > , & Handler ) ) ;
254
262
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
+ } ) ;
257
292
258
- report_inline_asm ( cgcx, & msg, cookie) ;
293
+ report_inline_asm ( cgcx, msg, cookie, source ) ;
259
294
}
260
295
261
296
unsafe 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
266
301
267
302
match llvm:: diagnostic:: Diagnostic :: unpack ( info) {
268
303
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 ) ;
270
305
}
271
306
272
307
llvm:: diagnostic:: Optimization ( opt) => {
0 commit comments