Skip to content

Commit 5541f68

Browse files
committed
Handle assembler warnings properly
1 parent ccac43b commit 5541f68

File tree

9 files changed

+124
-15
lines changed

9 files changed

+124
-15
lines changed

src/librustc_codegen_llvm/back/write.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, Mo
1616
use rustc_codegen_ssa::traits::*;
1717
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
1818
use rustc_data_structures::small_c_str::SmallCStr;
19-
use rustc_errors::{FatalError, Handler};
19+
use rustc_errors::{FatalError, Handler, Level};
2020
use rustc_fs_util::{link_or_copy, path_to_c_string};
2121
use rustc_hir::def_id::LOCAL_CRATE;
2222
use rustc_middle::bug;
@@ -242,6 +242,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
242242
fn report_inline_asm(
243243
cgcx: &CodegenContext<LlvmCodegenBackend>,
244244
msg: String,
245+
level: llvm::DiagnosticLevel,
245246
mut cookie: c_uint,
246247
source: Option<(String, Vec<InnerSpan>)>,
247248
) {
@@ -251,7 +252,12 @@ fn report_inline_asm(
251252
if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
252253
cookie = 0;
253254
}
254-
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source);
255+
let level = match level {
256+
llvm::DiagnosticLevel::Error => Level::Error,
257+
llvm::DiagnosticLevel::Warning => Level::Warning,
258+
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
259+
};
260+
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, level, source);
255261
}
256262

257263
unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) {
@@ -264,6 +270,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
264270
// diagnostics.
265271
let mut have_source = false;
266272
let mut buffer = String::new();
273+
let mut level = llvm::DiagnosticLevel::Error;
267274
let mut loc = 0;
268275
let mut ranges = [0; 8];
269276
let mut num_ranges = ranges.len() / 2;
@@ -273,6 +280,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
273280
diag,
274281
msg,
275282
buffer,
283+
&mut level,
276284
&mut loc,
277285
ranges.as_mut_ptr(),
278286
&mut num_ranges,
@@ -290,7 +298,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
290298
(buffer, spans)
291299
});
292300

293-
report_inline_asm(cgcx, msg, cookie, source);
301+
report_inline_asm(cgcx, msg, level, cookie, source);
294302
}
295303

296304
unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
@@ -301,7 +309,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
301309

302310
match llvm::diagnostic::Diagnostic::unpack(info) {
303311
llvm::diagnostic::InlineAsm(inline) => {
304-
report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None);
312+
report_inline_asm(
313+
cgcx,
314+
llvm::twine_to_string(inline.message),
315+
inline.level,
316+
inline.cookie,
317+
None,
318+
);
305319
}
306320

307321
llvm::diagnostic::Optimization(opt) => {

src/librustc_codegen_llvm/llvm/diagnostic.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ impl OptimizationDiagnostic<'ll> {
8888

8989
#[derive(Copy, Clone)]
9090
pub struct InlineAsmDiagnostic<'ll> {
91+
pub level: super::DiagnosticLevel,
9192
pub cookie: c_uint,
9293
pub message: &'ll Twine,
9394
pub instruction: Option<&'ll Value>,
@@ -98,10 +99,17 @@ impl InlineAsmDiagnostic<'ll> {
9899
let mut cookie = 0;
99100
let mut message = None;
100101
let mut instruction = None;
102+
let mut level = super::DiagnosticLevel::Error;
101103

102-
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut cookie, &mut message, &mut instruction);
104+
super::LLVMRustUnpackInlineAsmDiagnostic(
105+
di,
106+
&mut level,
107+
&mut cookie,
108+
&mut message,
109+
&mut instruction,
110+
);
103111

104-
InlineAsmDiagnostic { cookie, message: message.unwrap(), instruction }
112+
InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
105113
}
106114
}
107115

src/librustc_codegen_llvm/llvm/ffi.rs

+13
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,17 @@ pub enum DiagnosticKind {
489489
Linker,
490490
}
491491

492+
/// LLVMRustDiagnosticLevel
493+
#[derive(Copy, Clone)]
494+
#[repr(C)]
495+
#[allow(dead_code)] // Variants constructed by C++.
496+
pub enum DiagnosticLevel {
497+
Error,
498+
Warning,
499+
Note,
500+
Remark,
501+
}
502+
492503
/// LLVMRustArchiveKind
493504
#[derive(Copy, Clone)]
494505
#[repr(C)]
@@ -2054,6 +2065,7 @@ extern "C" {
20542065

20552066
pub fn LLVMRustUnpackInlineAsmDiagnostic(
20562067
DI: &'a DiagnosticInfo,
2068+
level_out: &mut DiagnosticLevel,
20572069
cookie_out: &mut c_uint,
20582070
message_out: &mut Option<&'a Twine>,
20592071
instruction_out: &mut Option<&'a Value>,
@@ -2074,6 +2086,7 @@ extern "C" {
20742086
d: &SMDiagnostic,
20752087
message_out: &RustString,
20762088
buffer_out: &RustString,
2089+
level_out: &mut DiagnosticLevel,
20772090
loc_out: &mut c_uint,
20782091
ranges_out: *mut c_uint,
20792092
num_ranges: &mut usize,

src/librustc_codegen_ssa/back/write.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -1551,7 +1551,7 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
15511551

15521552
enum SharedEmitterMessage {
15531553
Diagnostic(Diagnostic),
1554-
InlineAsmError(u32, String, Option<(String, Vec<InnerSpan>)>),
1554+
InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
15551555
AbortIfErrors,
15561556
Fatal(String),
15571557
}
@@ -1576,9 +1576,10 @@ impl SharedEmitter {
15761576
&self,
15771577
cookie: u32,
15781578
msg: String,
1579+
level: Level,
15791580
source: Option<(String, Vec<InnerSpan>)>,
15801581
) {
1581-
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source)));
1582+
drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
15821583
}
15831584

15841585
pub fn fatal(&self, msg: &str) {
@@ -1631,16 +1632,21 @@ impl SharedEmitterMain {
16311632
}
16321633
handler.emit_diagnostic(&d);
16331634
}
1634-
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => {
1635+
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
16351636
let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
16361637

1638+
let mut err = match level {
1639+
Level::Error => sess.struct_err(&msg),
1640+
Level::Warning => sess.struct_warn(&msg),
1641+
Level::Note => sess.struct_note_without_error(&msg),
1642+
_ => bug!("Invalid inline asm diagnostic level"),
1643+
};
1644+
16371645
// If the cookie is 0 then we don't have span information.
1638-
let mut err = if cookie == 0 {
1639-
sess.struct_err(&msg)
1640-
} else {
1646+
if cookie != 0 {
16411647
let pos = BytePos::from_u32(cookie);
16421648
let span = Span::with_root_ctxt(pos, pos);
1643-
sess.struct_span_err(span, &msg)
1649+
err.set_span(span);
16441650
};
16451651

16461652
// Point to the generated assembly if it is available.

src/librustc_errors/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,11 @@ impl Handler {
581581
DiagnosticBuilder::new(self, Level::Help, msg)
582582
}
583583

584+
/// Construct a builder at the `Note` level with the `msg`.
585+
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
586+
DiagnosticBuilder::new(self, Level::Note, msg)
587+
}
588+
584589
pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError {
585590
self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
586591
FatalError

src/librustc_session/session.rs

+3
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,9 @@ impl Session {
441441
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
442442
self.diagnostic().span_note_without_error(sp, msg)
443443
}
444+
pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
445+
self.diagnostic().struct_note_without_error(msg)
446+
}
444447

445448
pub fn diagnostic(&self) -> &rustc_errors::Handler {
446449
&self.parse_sess.span_diagnostic

src/rustllvm/RustWrapper.cpp

+46-1
Original file line numberDiff line numberDiff line change
@@ -1094,8 +1094,17 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
10941094
MessageOS << Opt->getMsg();
10951095
}
10961096

1097+
enum class LLVMRustDiagnosticLevel {
1098+
Error,
1099+
Warning,
1100+
Note,
1101+
Remark,
1102+
};
1103+
10971104
extern "C" void
1098-
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
1105+
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
1106+
LLVMRustDiagnosticLevel *LevelOut,
1107+
unsigned *CookieOut,
10991108
LLVMTwineRef *MessageOut,
11001109
LLVMValueRef *InstructionOut) {
11011110
// Undefined to call this not on an inline assembly diagnostic!
@@ -1105,6 +1114,23 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
11051114
*CookieOut = IA->getLocCookie();
11061115
*MessageOut = wrap(&IA->getMsgStr());
11071116
*InstructionOut = wrap(IA->getInstruction());
1117+
1118+
switch (IA->getSeverity()) {
1119+
case DS_Error:
1120+
*LevelOut = LLVMRustDiagnosticLevel::Error;
1121+
break;
1122+
case DS_Warning:
1123+
*LevelOut = LLVMRustDiagnosticLevel::Warning;
1124+
break;
1125+
case DS_Note:
1126+
*LevelOut = LLVMRustDiagnosticLevel::Note;
1127+
break;
1128+
case DS_Remark:
1129+
*LevelOut = LLVMRustDiagnosticLevel::Remark;
1130+
break;
1131+
default:
1132+
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1133+
}
11081134
}
11091135

11101136
extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
@@ -1166,6 +1192,7 @@ extern "C" LLVMRustDiagnosticKind
11661192
LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
11671193
return toRust((DiagnosticKind)unwrap(DI)->getKind());
11681194
}
1195+
11691196
// This is kept distinct from LLVMGetTypeKind, because when
11701197
// a new type kind is added, the Rust-side enum must be
11711198
// updated or UB will result.
@@ -1219,13 +1246,31 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
12191246
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
12201247
RustStringRef MessageOut,
12211248
RustStringRef BufferOut,
1249+
LLVMRustDiagnosticLevel* LevelOut,
12221250
unsigned* LocOut,
12231251
unsigned* RangesOut,
12241252
size_t* NumRanges) {
12251253
SMDiagnostic& D = *unwrap(DRef);
12261254
RawRustStringOstream MessageOS(MessageOut);
12271255
MessageOS << D.getMessage();
12281256

1257+
switch (D.getKind()) {
1258+
case SourceMgr::DK_Error:
1259+
*LevelOut = LLVMRustDiagnosticLevel::Error;
1260+
break;
1261+
case SourceMgr::DK_Warning:
1262+
*LevelOut = LLVMRustDiagnosticLevel::Warning;
1263+
break;
1264+
case SourceMgr::DK_Note:
1265+
*LevelOut = LLVMRustDiagnosticLevel::Note;
1266+
break;
1267+
case SourceMgr::DK_Remark:
1268+
*LevelOut = LLVMRustDiagnosticLevel::Remark;
1269+
break;
1270+
default:
1271+
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
1272+
}
1273+
12291274
if (D.getLoc() == SMLoc())
12301275
return false;
12311276

src/test/ui/asm/srcloc.rs

+3
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,8 @@ fn main() {
3737

3838
asm!(concat!("invalid", "_", "instruction"));
3939
//~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
40+
41+
asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
42+
//~^ WARN: scale factor without index register is ignored
4043
}
4144
}

src/test/ui/asm/srcloc.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,17 @@ note: instantiated into assembly here
7070
LL | invalid_instruction
7171
| ^^^^^^^^^^^^^^^^^^^
7272

73-
error: aborting due to 6 previous errors
73+
warning: scale factor without index register is ignored
74+
--> $DIR/srcloc.rs:41:15
75+
|
76+
LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
77+
| ^
78+
|
79+
note: instantiated into assembly here
80+
--> <inline asm>:1:23
81+
|
82+
LL | movaps %xmm3, (%esi, 2)
83+
| ^
84+
85+
error: aborting due to 6 previous errors; 1 warning emitted
7486

0 commit comments

Comments
 (0)