diff options
| author | bors <bors@rust-lang.org> | 2021-04-05 01:26:57 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-04-05 01:26:57 +0000 |
| commit | 015d2bc3fec48cef3cbfaec71c54fa31ce420853 (patch) | |
| tree | 78f07dccce940c12922d9af6e94143edee0e2ed4 /compiler/rustc_codegen_llvm/src/asm.rs | |
| parent | 35aa636159b84a771000ee025828798fd959933d (diff) | |
| parent | f8709ec96211b821c9fe8516d73d512eb718a15e (diff) | |
| download | rust-015d2bc3fec48cef3cbfaec71c54fa31ce420853.tar.gz rust-015d2bc3fec48cef3cbfaec71c54fa31ce420853.zip | |
Auto merge of #83864 - Dylan-DPC:rollup-78an86n, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #80525 (wasm64 support) - #83019 (core: disable `ptr::swap_nonoverlapping_one`'s block optimization on SPIR-V.) - #83717 (rustdoc: Separate filter-empty-string out into its own function) - #83807 (Tests: Remove redundant `ignore-tidy-linelength` annotations) - #83815 (ptr::addr_of documentation improvements) - #83820 (Remove attribute `#[link_args]`) - #83841 (Allow clobbering unsupported registers in asm!) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/asm.rs')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/asm.rs | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index e7d359c4f14..84b091d8d4d 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug}; -use rustc_span::{Pos, Span}; +use rustc_span::{Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -125,15 +125,39 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { // Collect the types of output operands let mut constraints = vec![]; + let mut clobbers = vec![]; let mut output_types = vec![]; let mut op_idx = FxHashMap::default(); for (idx, op) in operands.iter().enumerate() { match *op { InlineAsmOperandRef::Out { reg, late, place } => { + let is_target_supported = |reg_class: InlineAsmRegClass| { + for &(_, feature) in reg_class.supported_types(asm_arch) { + if let Some(feature) = feature { + if self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + { + return true; + } + } else { + // Register class is unconditionally supported + return true; + } + } + false + }; + let mut layout = None; let ty = if let Some(ref place) = place { layout = Some(&place.layout); llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout) + } else if !is_target_supported(reg.reg_class()) { + // We turn discarded outputs into clobber constraints + // if the target feature needed by the register class is + // disabled. This is necessary otherwise LLVM will try + // to actually allocate a register for the dummy output. + assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_))); + clobbers.push(format!("~{}", reg_to_llvm(reg, None))); + continue; } else { // If the output is discarded, we don't really care what // type is used. We're just using this to tell LLVM to @@ -244,6 +268,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } + constraints.append(&mut clobbers); if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { match asm_arch { InlineAsmArch::AArch64 | InlineAsmArch::Arm => { |
