Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #83864

Merged
merged 20 commits into from
Apr 5, 2021
Merged
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6530b32
rustdoc: use Array.prototype.filter instead of open-coding it
notriddle Mar 31, 2021
227f5ed
rustdoc: Separate filter-empty-string out into its own function
notriddle Apr 1, 2021
a4a6bdd
addr_of_mut: add example for creating a pointer to uninit data
RalfJung Apr 3, 2021
b93137a
explain that even addr_of cannot deref a NULL ptr
RalfJung Apr 3, 2021
5839bff
Remove attribute `#[link_args]`
petrochenkov Apr 3, 2021
3ea62cb
Remove redundant `ignore-tidy-linelength` annotations
sjakobi Apr 3, 2021
5d1747b
rely on intra-doc links
RalfJung Apr 4, 2021
ddc53f8
Allow clobbering unsupported registers in asm!
Amanieu Apr 4, 2021
31d0459
Update clobber example in the asm documentation
Amanieu Apr 4, 2021
da66a31
wasm64
devsnek Dec 30, 2020
b577d7e
fix typo
RalfJung Apr 4, 2021
3c3d3dd
core: rearrange `ptr::swap_nonoverlapping_one`'s cases (no functional…
eddyb Mar 11, 2021
bc6af97
core: disable `ptr::swap_nonoverlapping_one`'s block optimization on …
eddyb Mar 11, 2021
0d12422
Rollup merge of #80525 - devsnek:wasm64, r=nagisa
Dylan-DPC Apr 4, 2021
4e3f471
Rollup merge of #83019 - eddyb:spirv-no-block-swap, r=nagisa
Dylan-DPC Apr 4, 2021
03bd4d2
Rollup merge of #83717 - notriddle:main-js-slice-loop, r=GuillaumeGomez
Dylan-DPC Apr 4, 2021
ad776fd
Rollup merge of #83807 - sjakobi:77548-remove-ignore-annotations, r=M…
Dylan-DPC Apr 4, 2021
fbe89e2
Rollup merge of #83815 - RalfJung:addr_of, r=kennytm
Dylan-DPC Apr 4, 2021
3c2e4ff
Rollup merge of #83820 - petrochenkov:nolinkargs, r=nagisa
Dylan-DPC Apr 4, 2021
f8709ec
Rollup merge of #83841 - Amanieu:asm_clobber_feature, r=nagisa
Dylan-DPC Apr 4, 2021
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
Prev Previous commit
Next Next commit
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.
Amanieu committed Apr 4, 2021

Verified

This commit was signed with the committer’s verified signature.
MichaReiser Micha Reiser
commit ddc53f809b89001c08296b5b49fe1fcad1e566d5
82 changes: 50 additions & 32 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1499,46 +1499,64 @@ impl<'hir> LoweringContext<'_, 'hir> {
// previous iteration.
required_features.clear();

// Validate register classes against currently enabled target
// features. We check that at least one type is available for
// the current target.
let reg_class = reg.reg_class();
if reg_class == asm::InlineAsmRegClass::Err {
continue;
}
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
if let Some(feature) = feature {
if self.sess.target_features.contains(&Symbol::intern(feature)) {

// We ignore target feature requirements for clobbers: if the
// feature is disabled then the compiler doesn't care what we
// do with the registers.
//
// Note that this is only possible for explicit register
// operands, which cannot be used in the asm string.
let is_clobber = matches!(
op,
hir::InlineAsmOperand::Out {
reg: asm::InlineAsmRegOrRegClass::Reg(_),
late: _,
expr: None
}
);

if !is_clobber {
// Validate register classes against currently enabled target
// features. We check that at least one type is available for
// the current target.
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
if let Some(feature) = feature {
if self.sess.target_features.contains(&Symbol::intern(feature)) {
required_features.clear();
break;
} else {
required_features.push(feature);
}
} else {
required_features.clear();
break;
} else {
required_features.push(feature);
}
} else {
required_features.clear();
break;
}
}
// We are sorting primitive strs here and can use unstable sort here
required_features.sort_unstable();
required_features.dedup();
match &required_features[..] {
[] => {}
[feature] => {
let msg = format!(
"register class `{}` requires the `{}` target feature",
reg_class.name(),
feature
);
sess.struct_span_err(op_sp, &msg).emit();
}
features => {
let msg = format!(
"register class `{}` requires at least one target feature: {}",
reg_class.name(),
features.join(", ")
);
sess.struct_span_err(op_sp, &msg).emit();
// We are sorting primitive strs here and can use unstable sort here
required_features.sort_unstable();
required_features.dedup();
match &required_features[..] {
[] => {}
[feature] => {
let msg = format!(
"register class `{}` requires the `{}` target feature",
reg_class.name(),
feature
);
sess.struct_span_err(op_sp, &msg).emit();
}
features => {
let msg = format!(
"register class `{}` requires at least one target feature: {}",
reg_class.name(),
features.join(", ")
);
sess.struct_span_err(op_sp, &msg).emit();
}
}
}

27 changes: 26 additions & 1 deletion compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
@@ -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 => {
21 changes: 21 additions & 0 deletions src/test/codegen/asm-target-clobbers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// only-x86_64
// revisions: base avx512
// [avx512]compile-flags: -C target-feature=+avx512f

#![crate_type = "rlib"]
#![feature(asm)]

// CHECK-LABEL: @avx512_clobber
// base: call void asm sideeffect inteldialect "", "~{xmm31}"()
// avx512: call float asm sideeffect inteldialect "", "=&{xmm31}"()
#[no_mangle]
pub unsafe fn avx512_clobber() {
asm!("", out("zmm31") _, options(nostack, nomem, preserves_flags));
}

// CHECK-LABEL: @eax_clobber
// CHECK: call i32 asm sideeffect inteldialect "", "=&{ax}"()
#[no_mangle]
pub unsafe fn eax_clobber() {
asm!("", out("eax") _, options(nostack, nomem, preserves_flags));
}