Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_target::asm::*;
use crate::builder::Builder;
use crate::callee::get_fn;
use crate::context::CodegenCx;
use crate::errors::{NulBytesInAsm, UnwindingInlineAsm};
use crate::errors::{AsmGotoWithOutputs, NulBytesInAsm, UnwindingInlineAsm};
use crate::type_of::LayoutGccExt;

// Rust asm! and GCC Extended Asm semantics differ substantially.
Expand Down Expand Up @@ -545,6 +545,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
return;
}

// GCC's `asm goto` cannot have output operands (libgccjit rejects them with
// "cannot add output operand to asm goto"). Emit a clean error instead of
// letting libgccjit abort with an internal error.
if dest.is_some() && !outputs.is_empty() {
let err_sp = span.first().copied().unwrap_or(DUMMY_SP);
self.sess().dcx().emit_err(AsmGotoWithOutputs { span: err_sp });
return;
}

// 4. Generate Extended Asm block
let block = self.llbb();
let extended_asm = if let Some(dest) = dest {
Expand Down
7 changes: 7 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ pub(crate) struct NulBytesInAsm {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("GCC backend does not support `asm goto` with output operands")]
pub(crate) struct AsmGotoWithOutputs {
#[primary_span]
pub span: Span,
}
25 changes: 25 additions & 0 deletions tests/compile/asm_goto_with_outputs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Compiler:
// status: error
// stderr:
// error: GCC backend does not support `asm goto` with output operands
// ...

// Test that an `asm goto` with output operands emits a clean error instead of an
// ICE: libgccjit rejects output operands on an `asm goto` (issue #835).

#![feature(asm_goto_with_outputs)]

use std::arch::asm;

fn main() {
let mut a: i32 = 0;
unsafe {
asm!(
"jmp {op}",
inout("eax") a,
op = label { a = 7; },
options(nostack, nomem),
);
}
let _ = a;
}
8 changes: 7 additions & 1 deletion tests/lang_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,13 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) {
"lang compile",
"tests/compile",
TestMode::Compile,
&["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"],
&[
"simd-ffi.rs",
"asm_nul_byte.rs",
"asm_goto_with_outputs.rs",
"global_asm_nul_byte.rs",
"naked_asm_nul_byte.rs",
],
);
}

Expand Down
Loading