Rollup merge of #83841 - Amanieu:asm_clobber_feature, r=nagisa

Allow clobbering unsupported registers in asm!

Previously registers could only be marked as clobbered if the target feature for that register was enabled. This restriction is now removed.

cc #81092

r? ``@nagisa``
This commit is contained in:
Dylan DPC 2021-04-05 00:24:34 +02:00 committed by GitHub
commit f8709ec962
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 34 deletions

View file

@ -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 => {