Skip to content

Commit 887999d

Browse files
committed
Auto merge of rust-lang#88439 - cynecx:unwind_asm, r=Amanieu
Unwinding support for inline assembly r? `@Amanieu`
2 parents f581572 + 3dbb621 commit 887999d

File tree

55 files changed

+623
-232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+623
-232
lines changed

Diff for: compiler/rustc_ast/src/ast.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ pub enum InlineAsmRegOrRegClass {
19811981

19821982
bitflags::bitflags! {
19831983
#[derive(Encodable, Decodable, HashStable_Generic)]
1984-
pub struct InlineAsmOptions: u8 {
1984+
pub struct InlineAsmOptions: u16 {
19851985
const PURE = 1 << 0;
19861986
const NOMEM = 1 << 1;
19871987
const READONLY = 1 << 2;
@@ -1990,6 +1990,7 @@ bitflags::bitflags! {
19901990
const NOSTACK = 1 << 5;
19911991
const ATT_SYNTAX = 1 << 6;
19921992
const RAW = 1 << 7;
1993+
const MAY_UNWIND = 1 << 8;
19931994
}
19941995
}
19951996

Diff for: compiler/rustc_ast_lowering/src/asm.rs

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
4949
.struct_span_err(sp, "the `att_syntax` option is only supported on x86")
5050
.emit();
5151
}
52+
if asm.options.contains(InlineAsmOptions::MAY_UNWIND)
53+
&& !self.sess.features_untracked().asm_unwind
54+
{
55+
feature_err(
56+
&self.sess.parse_sess,
57+
sym::asm_unwind,
58+
sp,
59+
"the `may_unwind` option is unstable",
60+
)
61+
.emit();
62+
}
5263

5364
let mut clobber_abis = FxHashMap::default();
5465
if let Some(asm_arch) = asm_arch {

Diff for: compiler/rustc_ast_pretty/src/pprust/state.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,9 @@ impl<'a> State<'a> {
23382338
if opts.contains(InlineAsmOptions::RAW) {
23392339
options.push("raw");
23402340
}
2341+
if opts.contains(InlineAsmOptions::MAY_UNWIND) {
2342+
options.push("may_unwind");
2343+
}
23412344
s.commasep(Inconsistent, &options, |s, &opt| {
23422345
s.word(opt);
23432346
});

Diff for: compiler/rustc_borrowck/src/dataflow.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_middle::ty::RegionVid;
55
use rustc_middle::ty::TyCtxt;
66
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
77
use rustc_mir_dataflow::ResultsVisitable;
8-
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
8+
use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill};
99
use rustc_mir_dataflow::{Analysis, Direction, Results};
1010
use std::fmt;
1111
use std::iter;
@@ -434,9 +434,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
434434
&self,
435435
_trans: &mut impl GenKill<Self::Idx>,
436436
_block: mir::BasicBlock,
437-
_func: &mir::Operand<'tcx>,
438-
_args: &[mir::Operand<'tcx>],
439-
_dest_place: mir::Place<'tcx>,
437+
_return_places: CallReturnPlaces<'_, 'tcx>,
440438
) {
441439
}
442440
}

Diff for: compiler/rustc_borrowck/src/def_use.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
1717
PlaceContext::MutatingUse(MutatingUseContext::Store) |
1818

1919
// This is potentially both a def and a use...
20-
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
20+
PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput) |
2121

2222
// We let Call define the result in both the success and
2323
// unwind cases. This is not really correct, however it
@@ -26,6 +26,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
2626
// the def in call only to the input from the success
2727
// path and not the unwind path. -nmatsakis
2828
PlaceContext::MutatingUse(MutatingUseContext::Call) |
29+
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
2930
PlaceContext::MutatingUse(MutatingUseContext::Yield) |
3031

3132
// Storage live and storage dead aren't proper defines, but we can ignore

Diff for: compiler/rustc_borrowck/src/invalidation.rs

+1
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
199199
options: _,
200200
line_spans: _,
201201
destination: _,
202+
cleanup: _,
202203
} => {
203204
for op in operands {
204205
match *op {

Diff for: compiler/rustc_borrowck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
791791
options: _,
792792
line_spans: _,
793793
destination: _,
794+
cleanup: _,
794795
} => {
795796
for op in operands {
796797
match *op {

Diff for: compiler/rustc_borrowck/src/type_check/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1828,10 +1828,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18281828
self.assert_iscleanup(body, block_data, unwind, true);
18291829
}
18301830
}
1831-
TerminatorKind::InlineAsm { destination, .. } => {
1831+
TerminatorKind::InlineAsm { destination, cleanup, .. } => {
18321832
if let Some(target) = destination {
18331833
self.assert_iscleanup(body, block_data, target, is_cleanup);
18341834
}
1835+
if let Some(cleanup) = cleanup {
1836+
if is_cleanup {
1837+
span_mirbug!(self, block_data, "cleanup on cleanup block")
1838+
}
1839+
self.assert_iscleanup(body, block_data, cleanup, true);
1840+
}
18351841
}
18361842
}
18371843
}

Diff for: compiler/rustc_builtin_macros/src/asm.rs

+2
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ fn parse_options<'a>(
420420
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
421421
} else if p.eat_keyword(kw::Raw) {
422422
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
423+
} else if p.eat_keyword(sym::may_unwind) {
424+
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
423425
} else {
424426
return p.unexpected();
425427
}

Diff for: compiler/rustc_codegen_cranelift/src/base.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Codegen of a single function
22
33
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
4+
use rustc_ast::InlineAsmOptions;
45
use rustc_index::vec::IndexVec;
56
use rustc_middle::ty::adjustment::PointerCast;
67
use rustc_middle::ty::layout::FnAbiOf;
@@ -239,7 +240,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
239240
fx.add_comment(inst, terminator_head);
240241
}
241242

242-
fx.set_debug_loc(bb_data.terminator().source_info);
243+
let source_info = bb_data.terminator().source_info;
244+
fx.set_debug_loc(source_info);
243245

244246
match &bb_data.terminator().kind {
245247
TerminatorKind::Goto { target } => {
@@ -295,19 +297,19 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
295297
let len = codegen_operand(fx, len).load_scalar(fx);
296298
let index = codegen_operand(fx, index).load_scalar(fx);
297299
let location = fx
298-
.get_caller_location(bb_data.terminator().source_info.span)
300+
.get_caller_location(source_info.span)
299301
.load_scalar(fx);
300302

301303
codegen_panic_inner(
302304
fx,
303305
rustc_hir::LangItem::PanicBoundsCheck,
304306
&[index, len, location],
305-
bb_data.terminator().source_info.span,
307+
source_info.span,
306308
);
307309
}
308310
_ => {
309311
let msg_str = msg.description();
310-
codegen_panic(fx, msg_str, bb_data.terminator().source_info.span);
312+
codegen_panic(fx, msg_str, source_info.span);
311313
}
312314
}
313315
}
@@ -378,10 +380,18 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
378380
options,
379381
destination,
380382
line_spans: _,
383+
cleanup: _,
381384
} => {
385+
if options.contains(InlineAsmOptions::MAY_UNWIND) {
386+
fx.tcx.sess.span_fatal(
387+
source_info.span,
388+
"cranelift doesn't support unwinding from inline assembly.",
389+
);
390+
}
391+
382392
crate::inline_asm::codegen_inline_asm(
383393
fx,
384-
bb_data.terminator().source_info.span,
394+
source_info.span,
385395
template,
386396
operands,
387397
*options,
@@ -415,7 +425,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
415425
}
416426
TerminatorKind::Drop { place, target, unwind: _ } => {
417427
let drop_place = codegen_place(fx, *place);
418-
crate::abi::codegen_drop(fx, bb_data.terminator().source_info.span, drop_place);
428+
crate::abi::codegen_drop(fx, source_info.span, drop_place);
419429

420430
let target_block = fx.get_block(*target);
421431
fx.bcx.ins().jump(target_block, &[]);

Diff for: compiler/rustc_codegen_gcc/src/asm.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
118118
true
119119
}
120120

121-
fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) {
121+
fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) {
122+
if options.contains(InlineAsmOptions::MAY_UNWIND) {
123+
self.sess()
124+
.struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
125+
.emit();
126+
return;
127+
}
128+
122129
let asm_arch = self.tcx.sess.asm_arch.unwrap();
123130
let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64);
124131
let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX);

Diff for: compiler/rustc_codegen_llvm/src/asm.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::builder::Builder;
2+
use crate::common::Funclet;
23
use crate::context::CodegenCx;
34
use crate::llvm;
5+
use crate::llvm_util;
46
use crate::type_::Type;
57
use crate::type_of::LayoutLlvmExt;
68
use crate::value::Value;
@@ -98,6 +100,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
98100
ia.alignstack,
99101
ia.dialect,
100102
&[span],
103+
false,
104+
None,
101105
);
102106
if r.is_none() {
103107
return false;
@@ -121,6 +125,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
121125
options: InlineAsmOptions,
122126
line_spans: &[Span],
123127
instance: Instance<'_>,
128+
dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
124129
) {
125130
let asm_arch = self.tcx.sess.asm_arch.unwrap();
126131

@@ -355,6 +360,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
355360
alignstack,
356361
dialect,
357362
line_spans,
363+
options.contains(InlineAsmOptions::MAY_UNWIND),
364+
dest_catch_funclet,
358365
)
359366
.unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed"));
360367

@@ -447,9 +454,16 @@ pub(crate) fn inline_asm_call(
447454
alignstack: bool,
448455
dia: LlvmAsmDialect,
449456
line_spans: &[Span],
457+
unwind: bool,
458+
dest_catch_funclet: Option<(
459+
&'ll llvm::BasicBlock,
460+
&'ll llvm::BasicBlock,
461+
Option<&Funclet<'ll>>,
462+
)>,
450463
) -> Option<&'ll Value> {
451464
let volatile = if volatile { llvm::True } else { llvm::False };
452465
let alignstack = if alignstack { llvm::True } else { llvm::False };
466+
let can_throw = if unwind { llvm::True } else { llvm::False };
453467

454468
let argtys = inputs
455469
.iter()
@@ -466,6 +480,13 @@ pub(crate) fn inline_asm_call(
466480
let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len());
467481
debug!("constraint verification result: {:?}", constraints_ok);
468482
if constraints_ok {
483+
if unwind && llvm_util::get_version() < (13, 0, 0) {
484+
bx.cx.sess().span_fatal(
485+
line_spans[0],
486+
"unwinding from inline assembly is only supported on llvm >= 13.",
487+
);
488+
}
489+
469490
let v = llvm::LLVMRustInlineAsm(
470491
fty,
471492
asm.as_ptr().cast(),
@@ -475,8 +496,14 @@ pub(crate) fn inline_asm_call(
475496
volatile,
476497
alignstack,
477498
llvm::AsmDialect::from_generic(dia),
499+
can_throw,
478500
);
479-
let call = bx.call(fty, v, inputs, None);
501+
502+
let call = if let Some((dest, catch, funclet)) = dest_catch_funclet {
503+
bx.invoke(fty, v, inputs, dest, catch, funclet)
504+
} else {
505+
bx.call(fty, v, inputs, None)
506+
};
480507

481508
// Store mark in a metadata node so we can map LLVM errors
482509
// back to source locations. See #17552.

Diff for: compiler/rustc_codegen_llvm/src/intrinsic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
350350
false,
351351
ast::LlvmAsmDialect::Att,
352352
&[span],
353+
false,
354+
None,
353355
)
354356
.unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
355357

Diff for: compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,7 @@ extern "C" {
18471847
SideEffects: Bool,
18481848
AlignStack: Bool,
18491849
Dialect: AsmDialect,
1850+
CanThrow: Bool,
18501851
) -> &Value;
18511852
pub fn LLVMRustInlineAsmVerify(
18521853
Ty: &Type,

Diff for: compiler/rustc_codegen_ssa/src/mir/analyze.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
211211

212212
PlaceContext::MutatingUse(
213213
MutatingUseContext::Store
214+
| MutatingUseContext::LlvmAsmOutput
214215
| MutatingUseContext::AsmOutput
215216
| MutatingUseContext::Borrow
216217
| MutatingUseContext::AddressOf
@@ -275,9 +276,9 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
275276
| TerminatorKind::SwitchInt { .. }
276277
| TerminatorKind::Yield { .. }
277278
| TerminatorKind::FalseEdge { .. }
278-
| TerminatorKind::FalseUnwind { .. }
279-
| TerminatorKind::InlineAsm { .. } => { /* nothing to do */ }
279+
| TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
280280
TerminatorKind::Call { cleanup: unwind, .. }
281+
| TerminatorKind::InlineAsm { cleanup: unwind, .. }
281282
| TerminatorKind::Assert { cleanup: unwind, .. }
282283
| TerminatorKind::DropAndReplace { unwind, .. }
283284
| TerminatorKind::Drop { unwind, .. } => {

0 commit comments

Comments
 (0)