1
Fork 0

Auto merge of #133433 - matthiaskrgr:rollup-lfa3wp1, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #131523 (Fix asm goto with outputs and move it to a separate feature gate)
 - #131664 (Support input/output in vector registers of s390x inline assembly (under asm_experimental_reg feature))
 - #132432 (Add a test to verify that libstd doesn't use protected symbols)
 - #132502 (Document possibility to set core features in example config.toml)
 - #132529 (ci(triagebot): add more top-level files to A-meta)
 - #132533 (Add BorrowedBuf::into_filled{,_mut} methods to allow returning buffer with original lifetime)
 - #132803 (Fix broken url)
 - #132982 (alloc: fix `Allocator` method names in `alloc` free function docs)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-11-25 08:13:44 +00:00
commit 1278dad1e9
34 changed files with 1658 additions and 201 deletions

View file

@ -152,6 +152,8 @@ ast_lowering_register2 = register `{$reg2_name}`
ast_lowering_register_class_only_clobber = ast_lowering_register_class_only_clobber =
register class `{$reg_class_name}` can only be used as a clobber, not as an input or output register class `{$reg_class_name}` can only be used as a clobber, not as an input or output
ast_lowering_register_class_only_clobber_stable =
register class `{$reg_class_name}` can only be used as a clobber in stable
ast_lowering_register_conflict = ast_lowering_register_conflict =
register `{$reg1_name}` conflicts with register `{$reg2_name}` register `{$reg1_name}` conflicts with register `{$reg2_name}`
@ -181,6 +183,8 @@ ast_lowering_underscore_expr_lhs_assign =
.label = `_` not allowed here .label = `_` not allowed here
ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture
ast_lowering_unstable_inline_assembly_label_operand_with_outputs =
using both label and output operands for inline assembly is unstable
ast_lowering_unstable_inline_assembly_label_operands = ast_lowering_unstable_inline_assembly_label_operands =
label operands for inline assembly are unstable label operands for inline assembly are unstable
ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable

View file

@ -17,7 +17,8 @@ use super::errors::{
InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst, InlineAsmUnsupportedTarget, InvalidAbiClobberAbi, InvalidAsmTemplateModifierConst,
InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass, InvalidAsmTemplateModifierLabel, InvalidAsmTemplateModifierRegClass,
InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister, InvalidAsmTemplateModifierRegClassSub, InvalidAsmTemplateModifierSym, InvalidRegister,
InvalidRegisterClass, RegisterClassOnlyClobber, RegisterConflict, InvalidRegisterClass, RegisterClassOnlyClobber, RegisterClassOnlyClobberStable,
RegisterConflict,
}; };
use crate::{ use crate::{
AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, ParamMode,
@ -61,6 +62,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.emit(); .emit();
} }
} }
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
&& !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)) && !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
&& !self.tcx.sess.opts.actually_rustdoc && !self.tcx.sess.opts.actually_rustdoc
@ -239,15 +241,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
InlineAsmOperand::Label { block } => { InlineAsmOperand::Label { block } => {
if !self.tcx.features().asm_goto() {
feature_err(
sess,
sym::asm_goto,
*op_sp,
fluent::ast_lowering_unstable_inline_assembly_label_operands,
)
.emit();
}
hir::InlineAsmOperand::Label { block: self.lower_block(block, false) } hir::InlineAsmOperand::Label { block: self.lower_block(block, false) }
} }
}; };
@ -333,11 +326,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// means that we disallow passing a value in/out of the asm and // means that we disallow passing a value in/out of the asm and
// require that the operand name an explicit register, not a // require that the operand name an explicit register, not a
// register class. // register class.
if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { if reg_class.is_clobber_only(asm_arch.unwrap(), allow_experimental_reg)
self.dcx().emit_err(RegisterClassOnlyClobber { && !op.is_clobber()
op_span: op_sp, {
reg_class_name: reg_class.name(), if allow_experimental_reg || reg_class.is_clobber_only(asm_arch.unwrap(), true)
}); {
// always clobber-only
self.dcx().emit_err(RegisterClassOnlyClobber {
op_span: op_sp,
reg_class_name: reg_class.name(),
});
} else {
// clobber-only in stable
self.tcx
.sess
.create_feature_err(
RegisterClassOnlyClobberStable {
op_span: op_sp,
reg_class_name: reg_class.name(),
},
sym::asm_experimental_reg,
)
.emit();
}
continue; continue;
} }
@ -466,6 +477,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
// Feature gate checking for asm goto.
if let Some((_, op_sp)) =
operands.iter().find(|(op, _)| matches!(op, hir::InlineAsmOperand::Label { .. }))
{
if !self.tcx.features().asm_goto() {
feature_err(
sess,
sym::asm_goto,
*op_sp,
fluent::ast_lowering_unstable_inline_assembly_label_operands,
)
.emit();
}
// In addition, check if an output operand is used.
// This is gated behind an additional feature.
let output_operand_used = operands.iter().any(|(op, _)| {
matches!(
op,
hir::InlineAsmOperand::Out { expr: Some(_), .. }
| hir::InlineAsmOperand::InOut { .. }
| hir::InlineAsmOperand::SplitInOut { out_expr: Some(_), .. }
)
});
if output_operand_used && !self.tcx.features().asm_goto_with_outputs() {
feature_err(
sess,
sym::asm_goto_with_outputs,
*op_sp,
fluent::ast_lowering_unstable_inline_assembly_label_operand_with_outputs,
)
.emit();
}
}
let operands = self.arena.alloc_from_iter(operands); let operands = self.arena.alloc_from_iter(operands);
let template = self.arena.alloc_from_iter(asm.template.iter().cloned()); let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
let template_strs = self.arena.alloc_from_iter( let template_strs = self.arena.alloc_from_iter(

View file

@ -279,6 +279,14 @@ pub(crate) struct RegisterClassOnlyClobber {
pub reg_class_name: Symbol, pub reg_class_name: Symbol,
} }
#[derive(Diagnostic)]
#[diag(ast_lowering_register_class_only_clobber_stable)]
pub(crate) struct RegisterClassOnlyClobberStable {
#[primary_span]
pub op_span: Span,
pub reg_class_name: Symbol,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(ast_lowering_register_conflict)] #[diag(ast_lowering_register_conflict)]
pub(crate) struct RegisterConflict<'a> { pub(crate) struct RegisterConflict<'a> {

View file

@ -300,7 +300,10 @@ pub fn parse_asm_args<'a>(
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
} }
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { if args.options.contains(ast::InlineAsmOptions::NORETURN)
&& !outputs_sp.is_empty()
&& labels_sp.is_empty()
{
let err = dcx.create_err(errors::AsmNoReturn { outputs_sp }); let err = dcx.create_err(errors::AsmNoReturn { outputs_sp });
// Bail out now since this is likely to confuse MIR // Bail out now since this is likely to confuse MIR
return Err(err); return Err(err);

View file

@ -462,8 +462,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
let mut slots_output = vec![None; self.operands.len()]; let mut slots_output = vec![None; self.operands.len()];
let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| { let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| {
let reg_size = let reg_size = reg_class
reg_class.supported_types(self.arch).iter().map(|(ty, _)| ty.size()).max().unwrap(); .supported_types(self.arch, true)
.iter()
.map(|(ty, _)| ty.size())
.max()
.unwrap();
let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap();
let offset = slot_size.align_to(align); let offset = slot_size.align_to(align);
*slot_size = offset + reg_size; *slot_size = offset + reg_size;

View file

@ -186,7 +186,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// `clobber_abi` can add lots of clobbers that are not supported by the target, // `clobber_abi` can add lots of clobbers that are not supported by the target,
// such as AVX-512 registers, so we just ignore unsupported registers // such as AVX-512 registers, so we just ignore unsupported registers
let is_target_supported = let is_target_supported =
reg.reg_class().supported_types(asm_arch).iter().any( reg.reg_class().supported_types(asm_arch, true).iter().any(
|&(_, feature)| { |&(_, feature)| {
if let Some(feature) = feature { if let Some(feature) = feature {
self.tcx self.tcx
@ -683,9 +683,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::S390x( InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg, InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
@ -766,7 +765,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr, S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
) => cx.type_i32(), ) => cx.type_i32(),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2),
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),

View file

@ -45,7 +45,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
match *op { match *op {
InlineAsmOperandRef::Out { reg, late, place } => { InlineAsmOperandRef::Out { reg, late, place } => {
let is_target_supported = |reg_class: InlineAsmRegClass| { let is_target_supported = |reg_class: InlineAsmRegClass| {
for &(_, feature) in reg_class.supported_types(asm_arch) { for &(_, feature) in reg_class.supported_types(asm_arch, true) {
if let Some(feature) = feature { if let Some(feature) = feature {
if self if self
.tcx .tcx
@ -85,7 +85,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
} }
continue; continue;
} else if !is_target_supported(reg.reg_class()) } else if !is_target_supported(reg.reg_class())
|| reg.reg_class().is_clobber_only(asm_arch) || reg.reg_class().is_clobber_only(asm_arch, true)
{ {
// We turn discarded outputs into clobber constraints // We turn discarded outputs into clobber constraints
// if the target feature needed by the register class is // if the target feature needed by the register class is
@ -342,24 +342,32 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
} }
attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs }); attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });
// Switch to the 'normal' basic block if we did an `invoke` instead of a `call` // Write results to outputs. We need to do this for all possible control flow.
if let Some(dest) = dest { //
self.switch_to_block(dest); // Note that `dest` maybe populated with unreachable_block when asm goto with outputs
} // is used (because we need to codegen callbr which always needs a destination), so
// here we use the NORETURN option to determine if `dest` should be used.
for block in (if options.contains(InlineAsmOptions::NORETURN) { None } else { Some(dest) })
.into_iter()
.chain(labels.iter().copied().map(Some))
{
if let Some(block) = block {
self.switch_to_block(block);
}
// Write results to outputs for (idx, op) in operands.iter().enumerate() {
for (idx, op) in operands.iter().enumerate() { if let InlineAsmOperandRef::Out { reg, place: Some(place), .. }
if let InlineAsmOperandRef::Out { reg, place: Some(place), .. } | InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op
| InlineAsmOperandRef::InOut { reg, out_place: Some(place), .. } = *op {
{ let value = if output_types.len() == 1 {
let value = if output_types.len() == 1 { result
result } else {
} else { self.extract_value(result, op_idx[&idx] as u64)
self.extract_value(result, op_idx[&idx] as u64) };
}; let value =
let value = llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance);
llvm_fixup_output(self, value, reg.reg_class(), &place.layout, instance); OperandValue::Immediate(value).store(self, place);
OperandValue::Immediate(value).store(self, place); }
} }
} }
} }
@ -678,7 +686,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
S390x(S390xInlineAsmRegClass::reg) => "r", S390x(S390xInlineAsmRegClass::reg) => "r",
S390x(S390xInlineAsmRegClass::reg_addr) => "a", S390x(S390xInlineAsmRegClass::reg_addr) => "a",
S390x(S390xInlineAsmRegClass::freg) => "f", S390x(S390xInlineAsmRegClass::freg) => "f",
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { S390x(S390xInlineAsmRegClass::vreg) => "v",
S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
Sparc(SparcInlineAsmRegClass::reg) => "r", Sparc(SparcInlineAsmRegClass::reg) => "r",
@ -844,7 +853,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(), S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(),
S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => { S390x(S390xInlineAsmRegClass::vreg) => cx.type_vector(cx.type_i64(), 2),
S390x(S390xInlineAsmRegClass::areg) => {
unreachable!("clobber-only") unreachable!("clobber-only")
} }
Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),

View file

@ -376,8 +376,12 @@ declare_features! (
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
/// Enables experimental inline assembly support for additional architectures. /// Enables experimental inline assembly support for additional architectures.
(unstable, asm_experimental_arch, "1.58.0", Some(93335)), (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
/// Enables experimental register support in inline assembly.
(unstable, asm_experimental_reg, "CURRENT_RUSTC_VERSION", Some(133416)),
/// Allows using `label` operands in inline assembly. /// Allows using `label` operands in inline assembly.
(unstable, asm_goto, "1.78.0", Some(119364)), (unstable, asm_goto, "1.78.0", Some(119364)),
/// Allows using `label` operands in inline assembly together with output operands.
(unstable, asm_goto_with_outputs, "CURRENT_RUSTC_VERSION", Some(119364)),
/// Allows the `may_unwind` option in inline assembly. /// Allows the `may_unwind` option in inline assembly.
(unstable, asm_unwind, "1.58.0", Some(93334)), (unstable, asm_unwind, "1.58.0", Some(93334)),
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`. /// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.

View file

@ -431,6 +431,9 @@ hir_analysis_recursive_generic_parameter = {$param_def_kind} `{$param_name}` is
hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}` hir_analysis_redundant_lifetime_args = unnecessary lifetime parameter `{$victim}`
.note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}` .note = you can use the `{$candidate}` lifetime directly, in place of `{$victim}`
hir_analysis_register_type_unstable =
type `{$ty}` cannot be used with this register class in stable
hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}` hir_analysis_requires_note = the `{$trait_name}` impl for `{$ty}` requires that `{$error_predicate}`
hir_analysis_return_type_notation_equality_bound = hir_analysis_return_type_notation_equality_bound =

View file

@ -7,12 +7,14 @@ use rustc_hir::{self as hir, LangItem};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::Symbol;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, sym};
use rustc_target::asm::{ use rustc_target::asm::{
InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo, InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
}; };
use crate::errors::RegisterTypeUnstable;
pub struct InlineAsmCtxt<'a, 'tcx> { pub struct InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
@ -218,17 +220,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check the type against the list of types supported by the selected // Check the type against the list of types supported by the selected
// register class. // register class.
let asm_arch = self.tcx.sess.asm_arch.unwrap(); let asm_arch = self.tcx.sess.asm_arch.unwrap();
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
let reg_class = reg.reg_class(); let reg_class = reg.reg_class();
let supported_tys = reg_class.supported_types(asm_arch); let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg);
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else { let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
let msg = format!("type `{ty}` cannot be used with this register class"); let mut err = if !allow_experimental_reg
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); && reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty)
let supported_tys: Vec<_> = supported_tys.iter().map(|(t, _)| t.to_string()).collect(); {
err.note(format!( self.tcx.sess.create_feature_err(
"register class `{}` supports these types: {}", RegisterTypeUnstable { span: expr.span, ty },
reg_class.name(), sym::asm_experimental_reg,
supported_tys.join(", "), )
)); } else {
let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg);
let supported_tys: Vec<_> =
supported_tys.iter().map(|(t, _)| t.to_string()).collect();
err.note(format!(
"register class `{}` supports these types: {}",
reg_class.name(),
supported_tys.join(", "),
));
err
};
if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) { if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) {
err.help(format!("consider using the `{}` register class instead", suggest.name())); err.help(format!("consider using the `{}` register class instead", suggest.name()));
} }
@ -313,6 +327,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
self.tcx.dcx().delayed_bug("target architecture does not support asm"); self.tcx.dcx().delayed_bug("target architecture does not support asm");
return; return;
}; };
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
// Validate register classes against currently enabled target // Validate register classes against currently enabled target
// features. We check that at least one type is available for // features. We check that at least one type is available for
@ -352,7 +367,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if let InlineAsmRegClass::Err = reg_class { if let InlineAsmRegClass::Err = reg_class {
continue; continue;
} }
for &(_, feature) in reg_class.supported_types(asm_arch) { for &(_, feature) in reg_class.supported_types(asm_arch, allow_experimental_reg)
{
match feature { match feature {
Some(feature) => { Some(feature) => {
if target_features.contains(&feature) { if target_features.contains(&feature) {

View file

@ -1708,3 +1708,11 @@ pub(crate) struct CmseEntryGeneric {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag(hir_analysis_register_type_unstable)]
pub(crate) struct RegisterTypeUnstable<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
}

View file

@ -416,7 +416,9 @@ symbols! {
asm, asm,
asm_const, asm_const,
asm_experimental_arch, asm_experimental_arch,
asm_experimental_reg,
asm_goto, asm_goto,
asm_goto_with_outputs,
asm_sym, asm_sym,
asm_unwind, asm_unwind,
assert, assert,
@ -2139,6 +2141,7 @@ symbols! {
vec_pop, vec_pop,
vec_with_capacity, vec_with_capacity,
vecdeque_iter, vecdeque_iter,
vector,
version, version,
vfp2, vfp2,
vis, vis,

View file

@ -604,9 +604,13 @@ impl InlineAsmRegClass {
/// Returns a list of supported types for this register class, each with an /// Returns a list of supported types for this register class, each with an
/// options target feature required to use this type. /// options target feature required to use this type.
///
/// At the codegen stage, it is fine to always pass true for `allow_experimental_reg`,
/// since all the stability checking will have been done in prior stages.
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
allow_experimental_reg: bool,
) -> &'static [(InlineAsmType, Option<Symbol>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::X86(r) => r.supported_types(arch), Self::X86(r) => r.supported_types(arch),
@ -618,7 +622,7 @@ impl InlineAsmRegClass {
Self::Hexagon(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch),
Self::LoongArch(r) => r.supported_types(arch), Self::LoongArch(r) => r.supported_types(arch),
Self::Mips(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch),
Self::S390x(r) => r.supported_types(arch), Self::S390x(r) => r.supported_types(arch, allow_experimental_reg),
Self::Sparc(r) => r.supported_types(arch), Self::Sparc(r) => r.supported_types(arch),
Self::SpirV(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch),
Self::Wasm(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch),
@ -696,8 +700,11 @@ impl InlineAsmRegClass {
/// Returns whether registers in this class can only be used as clobbers /// Returns whether registers in this class can only be used as clobbers
/// and not as inputs/outputs. /// and not as inputs/outputs.
pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool { ///
self.supported_types(arch).is_empty() /// At the codegen stage, it is fine to always pass true for `allow_experimental_reg`,
/// since all the stability checking will have been done in prior stages.
pub fn is_clobber_only(self, arch: InlineAsmArch, allow_experimental_reg: bool) -> bool {
self.supported_types(arch, allow_experimental_reg).is_empty()
} }
} }

View file

@ -38,11 +38,22 @@ impl S390xInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
allow_experimental_reg: bool,
) -> &'static [(InlineAsmType, Option<Symbol>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; }, Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; },
Self::freg => types! { _: F32, F64; }, Self::freg => types! { _: F32, F64; },
Self::vreg => &[], Self::vreg => {
if allow_experimental_reg {
// non-clobber-only vector register support is unstable.
types! {
vector: I32, F32, I64, F64, I128, F128,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
}
} else {
&[]
}
}
Self::areg => &[], Self::areg => &[],
} }
} }

View file

@ -773,6 +773,7 @@
#validate-mir-opts = 3 #validate-mir-opts = 3
# Configure `std` features used during bootstrap. # Configure `std` features used during bootstrap.
#
# Default features will be expanded in the following cases: # Default features will be expanded in the following cases:
# - If `rust.llvm-libunwind` or `target.llvm-libunwind` is enabled: # - If `rust.llvm-libunwind` or `target.llvm-libunwind` is enabled:
# - "llvm-libunwind" will be added for in-tree LLVM builds. # - "llvm-libunwind" will be added for in-tree LLVM builds.
@ -780,6 +781,9 @@
# - If `rust.backtrace` is enabled, "backtrace" will be added. # - If `rust.backtrace` is enabled, "backtrace" will be added.
# - If `rust.profiler` or `target.profiler` is enabled, "profiler" will be added. # - If `rust.profiler` or `target.profiler` is enabled, "profiler" will be added.
# - If building for a zkvm target, "compiler-builtins-mem" will be added. # - If building for a zkvm target, "compiler-builtins-mem" will be added.
#
# Since libstd also builds libcore and liballoc as dependencies and all their features are mirrored
# as libstd features, this option can also be used to configure features such as optimize_for_size.
#std-features = ["panic_unwind"] #std-features = ["panic_unwind"]
# ============================================================================= # =============================================================================

View file

@ -61,7 +61,7 @@ pub use std::alloc::Global;
/// of the allocator registered with the `#[global_allocator]` attribute /// of the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crates default. /// if there is one, or the `std` crates default.
/// ///
/// This function is expected to be deprecated in favor of the `alloc` method /// This function is expected to be deprecated in favor of the `allocate` method
/// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// of the [`Global`] type when it and the [`Allocator`] trait become stable.
/// ///
/// # Safety /// # Safety
@ -106,7 +106,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
/// of the allocator registered with the `#[global_allocator]` attribute /// of the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crates default. /// if there is one, or the `std` crates default.
/// ///
/// This function is expected to be deprecated in favor of the `dealloc` method /// This function is expected to be deprecated in favor of the `deallocate` method
/// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// of the [`Global`] type when it and the [`Allocator`] trait become stable.
/// ///
/// # Safety /// # Safety
@ -125,7 +125,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
/// of the allocator registered with the `#[global_allocator]` attribute /// of the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crates default. /// if there is one, or the `std` crates default.
/// ///
/// This function is expected to be deprecated in favor of the `realloc` method /// This function is expected to be deprecated in favor of the `grow` and `shrink` methods
/// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// of the [`Global`] type when it and the [`Allocator`] trait become stable.
/// ///
/// # Safety /// # Safety
@ -145,7 +145,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
/// of the allocator registered with the `#[global_allocator]` attribute /// of the allocator registered with the `#[global_allocator]` attribute
/// if there is one, or the `std` crates default. /// if there is one, or the `std` crates default.
/// ///
/// This function is expected to be deprecated in favor of the `alloc_zeroed` method /// This function is expected to be deprecated in favor of the `allocate_zeroed` method
/// of the [`Global`] type when it and the [`Allocator`] trait become stable. /// of the [`Global`] type when it and the [`Allocator`] trait become stable.
/// ///
/// # Safety /// # Safety

View file

@ -108,6 +108,26 @@ impl<'data> BorrowedBuf<'data> {
} }
} }
/// Returns a shared reference to the filled portion of the buffer with its original lifetime.
#[inline]
pub fn into_filled(self) -> &'data [u8] {
// SAFETY: We only slice the filled part of the buffer, which is always valid
unsafe {
let buf = self.buf.get_unchecked(..self.filled);
MaybeUninit::slice_assume_init_ref(buf)
}
}
/// Returns a mutable reference to the filled portion of the buffer with its original lifetime.
#[inline]
pub fn into_filled_mut(self) -> &'data mut [u8] {
// SAFETY: We only slice the filled part of the buffer, which is always valid
unsafe {
let buf = self.buf.get_unchecked_mut(..self.filled);
MaybeUninit::slice_assume_init_mut(buf)
}
}
/// Returns a cursor over the unfilled part of the buffer. /// Returns a cursor over the unfilled part of the buffer.
#[inline] #[inline]
pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> { pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> {

View file

@ -0,0 +1,40 @@
# `asm_experimental_arch`
The tracking issue for this feature is: [#133416]
[#133416]: https://github.com/rust-lang/rust/issues/133416
------------------------
This tracks support for additional registers in architectures where inline assembly is already stable.
## Register classes
| Architecture | Register class | Registers | LLVM constraint code |
| ------------ | -------------- | --------- | -------------------- |
| s390x | `vreg` | `v[0-31]` | `v` |
> **Notes**:
> - s390x `vreg` is clobber-only in stable.
## Register class supported types
| Architecture | Register class | Target feature | Allowed types |
| ------------ | -------------- | -------------- | ------------- |
| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
## Register aliases
| Architecture | Base register | Aliases |
| ------------ | ------------- | ------- |
## Unsupported registers
| Architecture | Unsupported register | Reason |
| ------------ | -------------------- | ------ |
## Template modifiers
| Architecture | Register class | Modifier | Example output | LLVM modifier |
| ------------ | -------------- | -------- | -------------- | ------------- |
| s390x | `vreg` | None | `%v0` | None |

View file

@ -32,7 +32,7 @@ from lldb import SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
# You can find more information and examples here: # You can find more information and examples here:
# 1. https://lldb.llvm.org/varformats.html # 1. https://lldb.llvm.org/varformats.html
# 2. https://lldb.llvm.org/use/python-reference.html # 2. https://lldb.llvm.org/use/python-reference.html
# 3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html # 3. https://github.com/llvm/llvm-project/blob/llvmorg-8.0.1/lldb/www/python_reference/lldb.formatters.cpp-pysrc.html
# 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa # 4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa
#################################################################################################### ####################################################################################################

View file

@ -1,10 +1,13 @@
//@ revisions: s390x //@ revisions: s390x s390x_vector
//@ assembly-output: emit-asm //@ assembly-output: emit-asm
//@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] compile-flags: --target s390x-unknown-linux-gnu
//@[s390x] needs-llvm-components: systemz //@[s390x] needs-llvm-components: systemz
//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector] needs-llvm-components: systemz
//@ compile-flags: -Zmerge-functions=disabled //@ compile-flags: -Zmerge-functions=disabled
#![feature(no_core, lang_items, rustc_attrs, repr_simd)] #![feature(no_core, lang_items, rustc_attrs, repr_simd, f128)]
#![cfg_attr(s390x_vector, feature(asm_experimental_reg))]
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![no_core] #![no_core]
#![allow(asm_sub_register, non_camel_case_types)] #![allow(asm_sub_register, non_camel_case_types)]
@ -27,16 +30,39 @@ trait Sized {}
#[lang = "copy"] #[lang = "copy"]
trait Copy {} trait Copy {}
impl<T: Copy, const N: usize> Copy for [T; N] {}
type ptr = *const i32; type ptr = *const i32;
#[repr(simd)]
pub struct i8x16([i8; 16]);
#[repr(simd)]
pub struct i16x8([i16; 8]);
#[repr(simd)]
pub struct i32x4([i32; 4]);
#[repr(simd)]
pub struct i64x2([i64; 2]);
#[repr(simd)]
pub struct f32x4([f32; 4]);
#[repr(simd)]
pub struct f64x2([f64; 2]);
impl Copy for i8 {} impl Copy for i8 {}
impl Copy for u8 {} impl Copy for u8 {}
impl Copy for i16 {} impl Copy for i16 {}
impl Copy for i32 {} impl Copy for i32 {}
impl Copy for i64 {} impl Copy for i64 {}
impl Copy for i128 {}
impl Copy for f32 {} impl Copy for f32 {}
impl Copy for f64 {} impl Copy for f64 {}
impl Copy for f128 {}
impl Copy for ptr {} impl Copy for ptr {}
impl Copy for i8x16 {}
impl Copy for i16x8 {}
impl Copy for i32x4 {}
impl Copy for i64x2 {}
impl Copy for f32x4 {}
impl Copy for f64x2 {}
extern "C" { extern "C" {
fn extern_func(); fn extern_func();
@ -65,7 +91,6 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
// CHECK: #APP // CHECK: #APP
// CHECK: brasl %r14, extern_func // CHECK: brasl %r14, extern_func
// CHECK: #NO_APP // CHECK: #NO_APP
#[cfg(s390x)]
#[no_mangle] #[no_mangle]
pub unsafe fn sym_fn_32() { pub unsafe fn sym_fn_32() {
asm!("brasl %r14, {}", sym extern_func); asm!("brasl %r14, {}", sym extern_func);
@ -146,6 +171,90 @@ check!(reg_f64, f64, freg, "ldr");
// CHECK: #NO_APP // CHECK: #NO_APP
check!(reg_ptr, ptr, reg, "lgr"); check!(reg_ptr, ptr, reg, "lgr");
// s390x_vector-LABEL: vreg_i8x16:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i8x16, i8x16, vreg, "vlr");
// s390x_vector-LABEL: vreg_i16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i16x8, i16x8, vreg, "vlr");
// s390x_vector-LABEL: vreg_i32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i32x4, i32x4, vreg, "vlr");
// s390x_vector-LABEL: vreg_i64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i64x2, i64x2, vreg, "vlr");
// s390x_vector-LABEL: vreg_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f32x4, f32x4, vreg, "vlr");
// s390x_vector-LABEL: vreg_f64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f64x2, f64x2, vreg, "vlr");
// s390x_vector-LABEL: vreg_i32:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i32, i32, vreg, "vlr");
// s390x_vector-LABEL: vreg_i64:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i64, i64, vreg, "vlr");
// s390x_vector-LABEL: vreg_i128:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_i128, i128, vreg, "vlr");
// s390x_vector-LABEL: vreg_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f32, f32, vreg, "vlr");
// s390x_vector-LABEL: vreg_f64:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f64, f64, vreg, "vlr");
// s390x_vector-LABEL: vreg_f128:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f128, f128, vreg, "vlr");
// CHECK-LABEL: r0_i8: // CHECK-LABEL: r0_i8:
// CHECK: #APP // CHECK: #APP
// CHECK: lr %r0, %r0 // CHECK: lr %r0, %r0
@ -181,3 +290,87 @@ check_reg!(f0_f32, f32, "f0", "ler");
// CHECK: ldr %f0, %f0 // CHECK: ldr %f0, %f0
// CHECK: #NO_APP // CHECK: #NO_APP
check_reg!(f0_f64, f64, "f0", "ldr"); check_reg!(f0_f64, f64, "f0", "ldr");
// s390x_vector-LABEL: v0_i8x16:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i8x16, i8x16, "v0", "vlr");
// s390x_vector-LABEL: v0_i16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i16x8, i16x8, "v0", "vlr");
// s390x_vector-LABEL: v0_i32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i32x4, i32x4, "v0", "vlr");
// s390x_vector-LABEL: v0_i64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i64x2, i64x2, "v0", "vlr");
// s390x_vector-LABEL: v0_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f32x4, f32x4, "v0", "vlr");
// s390x_vector-LABEL: v0_f64x2:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f64x2, f64x2, "v0", "vlr");
// s390x_vector-LABEL: v0_i32:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i32, i32, "v0", "vlr");
// s390x_vector-LABEL: v0_i64:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i64, i64, "v0", "vlr");
// s390x_vector-LABEL: v0_i128:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_i128, i128, "v0", "vlr");
// s390x_vector-LABEL: v0_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f32, f32, "v0", "vlr");
// s390x_vector-LABEL: v0_f64:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f64, f64, "v0", "vlr");
// s390x_vector-LABEL: v0_f128:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f128, f128, "v0", "vlr");

View file

@ -45,6 +45,7 @@ impl_marker_trait!(
impl<'a, T: ?Sized> Copy for &'a T {} impl<'a, T: ?Sized> Copy for &'a T {}
impl<T: ?Sized> Copy for *const T {} impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {} impl<T: ?Sized> Copy for *mut T {}
impl<T: Copy, const N: usize> Copy for [T; N] {}
#[lang = "phantom_data"] #[lang = "phantom_data"]
pub struct PhantomData<T: ?Sized>; pub struct PhantomData<T: ?Sized>;

View file

@ -2,21 +2,10 @@
//@ only-x86_64 //@ only-x86_64
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![feature(asm_goto)] #![feature(asm_goto, asm_goto_with_outputs)]
use std::arch::asm; use std::arch::asm;
#[no_mangle]
pub extern "C" fn panicky() {}
struct Foo;
impl Drop for Foo {
fn drop(&mut self) {
println!();
}
}
// CHECK-LABEL: @asm_goto // CHECK-LABEL: @asm_goto
#[no_mangle] #[no_mangle]
pub unsafe fn asm_goto() { pub unsafe fn asm_goto() {
@ -38,14 +27,37 @@ pub unsafe fn asm_goto_with_outputs() -> u64 {
out out
} }
// CHECK-LABEL: @asm_goto_with_outputs_use_in_label
#[no_mangle]
pub unsafe fn asm_goto_with_outputs_use_in_label() -> u64 {
let out: u64;
// CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect "
// CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
asm!("{} /* {} */", out(reg) out, label { return out; });
// CHECK: [[JUMPBB]]:
// CHECK-NEXT: [[RET:%.+]] = phi i64 [ 1, %[[FALLTHROUGHBB]] ], [ [[RES]], %start ]
// CHECK-NEXT: ret i64 [[RET]]
1
}
// CHECK-LABEL: @asm_goto_noreturn // CHECK-LABEL: @asm_goto_noreturn
#[no_mangle] #[no_mangle]
pub unsafe fn asm_goto_noreturn() -> u64 { pub unsafe fn asm_goto_noreturn() -> u64 {
let out: u64;
// CHECK: callbr void asm sideeffect alignstack inteldialect " // CHECK: callbr void asm sideeffect alignstack inteldialect "
// CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]] // CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]]
asm!("jmp {}", label { return 1; }, options(noreturn)); asm!("jmp {}", label { return 1; }, options(noreturn));
// CHECK: [[JUMPBB]]: // CHECK: [[JUMPBB]]:
// CHECK-NEXT: ret i64 1 // CHECK-NEXT: ret i64 1
}
// CHECK-LABEL: @asm_goto_noreturn_with_outputs
#[no_mangle]
pub unsafe fn asm_goto_noreturn_with_outputs() -> u64 {
let out: u64;
// CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect "
// CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
asm!("mov {}, 1", "jmp {}", out(reg) out, label { return out; });
// CHECK: [[JUMPBB]]:
// CHECK-NEXT: ret i64 [[RES]]
out out
} }

View file

@ -0,0 +1,63 @@
// If libstd was compiled to use protected symbols, then linking would fail if GNU ld < 2.40 were
// used. This might not be noticed, since usually we use LLD for linking, so we could end up
// distributing a version of libstd that would cause link errors for such users.
//@ only-x86_64-unknown-linux-gnu
use run_make_support::object::Endianness;
use run_make_support::object::read::archive::ArchiveFile;
use run_make_support::object::read::elf::{FileHeader as _, SectionHeader as _};
use run_make_support::rfs::{read, read_dir};
use run_make_support::{has_prefix, has_suffix, object, path, rustc, shallow_find_files, target};
type FileHeader = run_make_support::object::elf::FileHeader64<Endianness>;
type SymbolTable<'data> = run_make_support::object::read::elf::SymbolTable<'data, FileHeader>;
fn main() {
// Find libstd-...rlib
let sysroot = rustc().print("sysroot").run().stdout_utf8();
let sysroot = sysroot.trim();
let target_sysroot = path(sysroot).join("lib/rustlib").join(target()).join("lib");
let mut libs = shallow_find_files(&target_sysroot, |path| {
has_prefix(path, "libstd-") && has_suffix(path, ".rlib")
});
assert_eq!(libs.len(), 1);
let libstd_path = libs.pop().unwrap();
let archive_data = read(libstd_path);
// Parse all the object files within the libstd archive, checking defined symbols.
let mut num_protected = 0;
let mut num_symbols = 0;
let archive = ArchiveFile::parse(&*archive_data).unwrap();
for member in archive.members() {
let member = member.unwrap();
if member.name() == b"lib.rmeta" {
continue;
}
let data = member.data(&*archive_data).unwrap();
let header = FileHeader::parse(data).unwrap();
let endian = header.endian().unwrap();
let sections = header.sections(endian, data).unwrap();
for (section_index, section) in sections.enumerate() {
if section.sh_type(endian) == object::elf::SHT_SYMTAB {
let symbols =
SymbolTable::parse(endian, data, &sections, section_index, section).unwrap();
for symbol in symbols.symbols() {
if symbol.st_visibility() == object::elf::STV_PROTECTED {
num_protected += 1;
}
num_symbols += 1;
}
}
}
}
// If there were no symbols at all, then something is wrong with the test.
assert_ne!(num_symbols, 0);
// The purpose of this test - check that no symbols have protected visibility.
assert_eq!(num_protected, 0);
}

View file

@ -1,19 +1,31 @@
//@ add-core-stubs //@ add-core-stubs
//@ needs-asm-support //@ needs-asm-support
//@ revisions: s390x //@ revisions: s390x s390x_vector s390x_vector_stable
//@[s390x] compile-flags: --target s390x-unknown-linux-gnu //@[s390x] compile-flags: --target s390x-unknown-linux-gnu
//@[s390x] needs-llvm-components: systemz //@[s390x] needs-llvm-components: systemz
//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector] needs-llvm-components: systemz
//@[s390x_vector_stable] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector_stable] needs-llvm-components: systemz
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![feature(no_core, rustc_attrs)] #![feature(no_core, rustc_attrs, repr_simd)]
#![feature(asm_experimental_arch)] #![cfg_attr(not(s390x_vector_stable), feature(asm_experimental_reg))]
#![no_core] #![no_core]
#![allow(non_camel_case_types)]
extern crate minicore; extern crate minicore;
use minicore::*; use minicore::*;
#[repr(simd)]
pub struct i64x2([i64; 2]);
impl Copy for i64x2 {}
fn f() { fn f() {
let mut x = 0; let mut x = 0;
let mut b = 0u8;
let mut v = i64x2([0; 2]);
unsafe { unsafe {
// Unsupported registers // Unsupported registers
asm!("", out("r11") _); asm!("", out("r11") _);
@ -57,6 +69,51 @@ fn f() {
asm!("", out("a1") _); asm!("", out("a1") _);
//~^ ERROR invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm //~^ ERROR invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
// vreg
asm!("", out("v0") _); // always ok
asm!("", in("v0") v); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658]
asm!("", out("v0") v); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658]
asm!("", in("v0") x); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658]
asm!("", out("v0") x); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658]
asm!("", in("v0") b);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class
//[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class
asm!("", out("v0") b);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class
//[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class
asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i64x2` cannot be used with this register class in stable [E0658]
asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `i32` cannot be used with this register class in stable [E0658]
asm!("/* {} */", in(vreg) b);
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector]~^^ ERROR type `u8` cannot be used with this register class
//[s390x_vector_stable]~^^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
//[s390x_vector_stable]~| ERROR type `u8` cannot be used with this register class
asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg
//[s390x]~^ ERROR register class `vreg` requires the `vector` target feature
//[s390x_vector_stable]~^^ ERROR register class `vreg` can only be used as a clobber in stable [E0658]
// Clobber-only registers // Clobber-only registers
// areg // areg
asm!("", out("a2") _); // ok asm!("", out("a2") _); // ok
@ -72,21 +129,6 @@ fn f() {
asm!("/* {} */", out(areg) _); asm!("/* {} */", out(areg) _);
//~^ ERROR can only be used as a clobber //~^ ERROR can only be used as a clobber
// vreg
asm!("", out("v0") _); // ok
// FIXME: will be supported in https://github.com/rust-lang/rust/pull/131664
asm!("", in("v0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("v0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(vreg) x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("/* {} */", out(vreg) _);
//~^ ERROR can only be used as a clobber
// Overlapping registers // Overlapping registers
// vreg/freg // vreg/freg
asm!("", out("v0") _, out("f0") _); asm!("", out("v0") _, out("f0") _);

View file

@ -1,173 +1,149 @@
error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:19:18 --> $DIR/bad-reg.rs:31:18
| |
LL | asm!("", out("r11") _); LL | asm!("", out("r11") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:21:18 --> $DIR/bad-reg.rs:33:18
| |
LL | asm!("", out("r15") _); LL | asm!("", out("r15") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:23:18 --> $DIR/bad-reg.rs:35:18
| |
LL | asm!("", out("c0") _); LL | asm!("", out("c0") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:25:18 --> $DIR/bad-reg.rs:37:18
| |
LL | asm!("", out("c1") _); LL | asm!("", out("c1") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:27:18 --> $DIR/bad-reg.rs:39:18
| |
LL | asm!("", out("c2") _); LL | asm!("", out("c2") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:29:18 --> $DIR/bad-reg.rs:41:18
| |
LL | asm!("", out("c3") _); LL | asm!("", out("c3") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:31:18 --> $DIR/bad-reg.rs:43:18
| |
LL | asm!("", out("c4") _); LL | asm!("", out("c4") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:33:18 --> $DIR/bad-reg.rs:45:18
| |
LL | asm!("", out("c5") _); LL | asm!("", out("c5") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:35:18 --> $DIR/bad-reg.rs:47:18
| |
LL | asm!("", out("c6") _); LL | asm!("", out("c6") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:37:18 --> $DIR/bad-reg.rs:49:18
| |
LL | asm!("", out("c7") _); LL | asm!("", out("c7") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:39:18 --> $DIR/bad-reg.rs:51:18
| |
LL | asm!("", out("c8") _); LL | asm!("", out("c8") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:41:18 --> $DIR/bad-reg.rs:53:18
| |
LL | asm!("", out("c9") _); LL | asm!("", out("c9") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:43:18 --> $DIR/bad-reg.rs:55:18
| |
LL | asm!("", out("c10") _); LL | asm!("", out("c10") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:45:18 --> $DIR/bad-reg.rs:57:18
| |
LL | asm!("", out("c11") _); LL | asm!("", out("c11") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:47:18 --> $DIR/bad-reg.rs:59:18
| |
LL | asm!("", out("c12") _); LL | asm!("", out("c12") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:49:18 --> $DIR/bad-reg.rs:61:18
| |
LL | asm!("", out("c13") _); LL | asm!("", out("c13") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:51:18 --> $DIR/bad-reg.rs:63:18
| |
LL | asm!("", out("c14") _); LL | asm!("", out("c14") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:53:18 --> $DIR/bad-reg.rs:65:18
| |
LL | asm!("", out("c15") _); LL | asm!("", out("c15") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:55:18 --> $DIR/bad-reg.rs:67:18
| |
LL | asm!("", out("a0") _); LL | asm!("", out("a0") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:57:18 --> $DIR/bad-reg.rs:69:18
| |
LL | asm!("", out("a1") _); LL | asm!("", out("a1") _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:63:18 --> $DIR/bad-reg.rs:120:18
| |
LL | asm!("", in("a2") x); LL | asm!("", in("a2") x);
| ^^^^^^^^^^ | ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:66:18 --> $DIR/bad-reg.rs:123:18
| |
LL | asm!("", out("a2") x); LL | asm!("", out("a2") x);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:69:26 --> $DIR/bad-reg.rs:126:26
| |
LL | asm!("/* {} */", in(areg) x); LL | asm!("/* {} */", in(areg) x);
| ^^^^^^^^^^ | ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:72:26 --> $DIR/bad-reg.rs:129:26
| |
LL | asm!("/* {} */", out(areg) _); LL | asm!("/* {} */", out(areg) _);
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:78:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:81:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:84:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^
error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:87:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^
error: register `f0` conflicts with register `v0` error: register `f0` conflicts with register `v0`
--> $DIR/bad-reg.rs:92:31 --> $DIR/bad-reg.rs:134:31
| |
LL | asm!("", out("v0") _, out("f0") _); LL | asm!("", out("v0") _, out("f0") _);
| ----------- ^^^^^^^^^^^ register `f0` | ----------- ^^^^^^^^^^^ register `f0`
@ -175,7 +151,7 @@ LL | asm!("", out("v0") _, out("f0") _);
| register `v0` | register `v0`
error: register `f1` conflicts with register `v1` error: register `f1` conflicts with register `v1`
--> $DIR/bad-reg.rs:94:31 --> $DIR/bad-reg.rs:136:31
| |
LL | asm!("", out("v1") _, out("f1") _); LL | asm!("", out("v1") _, out("f1") _);
| ----------- ^^^^^^^^^^^ register `f1` | ----------- ^^^^^^^^^^^ register `f1`
@ -183,7 +159,7 @@ LL | asm!("", out("v1") _, out("f1") _);
| register `v1` | register `v1`
error: register `f2` conflicts with register `v2` error: register `f2` conflicts with register `v2`
--> $DIR/bad-reg.rs:96:31 --> $DIR/bad-reg.rs:138:31
| |
LL | asm!("", out("v2") _, out("f2") _); LL | asm!("", out("v2") _, out("f2") _);
| ----------- ^^^^^^^^^^^ register `f2` | ----------- ^^^^^^^^^^^ register `f2`
@ -191,7 +167,7 @@ LL | asm!("", out("v2") _, out("f2") _);
| register `v2` | register `v2`
error: register `f3` conflicts with register `v3` error: register `f3` conflicts with register `v3`
--> $DIR/bad-reg.rs:98:31 --> $DIR/bad-reg.rs:140:31
| |
LL | asm!("", out("v3") _, out("f3") _); LL | asm!("", out("v3") _, out("f3") _);
| ----------- ^^^^^^^^^^^ register `f3` | ----------- ^^^^^^^^^^^ register `f3`
@ -199,7 +175,7 @@ LL | asm!("", out("v3") _, out("f3") _);
| register `v3` | register `v3`
error: register `f4` conflicts with register `v4` error: register `f4` conflicts with register `v4`
--> $DIR/bad-reg.rs:100:31 --> $DIR/bad-reg.rs:142:31
| |
LL | asm!("", out("v4") _, out("f4") _); LL | asm!("", out("v4") _, out("f4") _);
| ----------- ^^^^^^^^^^^ register `f4` | ----------- ^^^^^^^^^^^ register `f4`
@ -207,7 +183,7 @@ LL | asm!("", out("v4") _, out("f4") _);
| register `v4` | register `v4`
error: register `f5` conflicts with register `v5` error: register `f5` conflicts with register `v5`
--> $DIR/bad-reg.rs:102:31 --> $DIR/bad-reg.rs:144:31
| |
LL | asm!("", out("v5") _, out("f5") _); LL | asm!("", out("v5") _, out("f5") _);
| ----------- ^^^^^^^^^^^ register `f5` | ----------- ^^^^^^^^^^^ register `f5`
@ -215,7 +191,7 @@ LL | asm!("", out("v5") _, out("f5") _);
| register `v5` | register `v5`
error: register `f6` conflicts with register `v6` error: register `f6` conflicts with register `v6`
--> $DIR/bad-reg.rs:104:31 --> $DIR/bad-reg.rs:146:31
| |
LL | asm!("", out("v6") _, out("f6") _); LL | asm!("", out("v6") _, out("f6") _);
| ----------- ^^^^^^^^^^^ register `f6` | ----------- ^^^^^^^^^^^ register `f6`
@ -223,7 +199,7 @@ LL | asm!("", out("v6") _, out("f6") _);
| register `v6` | register `v6`
error: register `f7` conflicts with register `v7` error: register `f7` conflicts with register `v7`
--> $DIR/bad-reg.rs:106:31 --> $DIR/bad-reg.rs:148:31
| |
LL | asm!("", out("v7") _, out("f7") _); LL | asm!("", out("v7") _, out("f7") _);
| ----------- ^^^^^^^^^^^ register `f7` | ----------- ^^^^^^^^^^^ register `f7`
@ -231,7 +207,7 @@ LL | asm!("", out("v7") _, out("f7") _);
| register `v7` | register `v7`
error: register `f8` conflicts with register `v8` error: register `f8` conflicts with register `v8`
--> $DIR/bad-reg.rs:108:31 --> $DIR/bad-reg.rs:150:31
| |
LL | asm!("", out("v8") _, out("f8") _); LL | asm!("", out("v8") _, out("f8") _);
| ----------- ^^^^^^^^^^^ register `f8` | ----------- ^^^^^^^^^^^ register `f8`
@ -239,7 +215,7 @@ LL | asm!("", out("v8") _, out("f8") _);
| register `v8` | register `v8`
error: register `f9` conflicts with register `v9` error: register `f9` conflicts with register `v9`
--> $DIR/bad-reg.rs:110:31 --> $DIR/bad-reg.rs:152:31
| |
LL | asm!("", out("v9") _, out("f9") _); LL | asm!("", out("v9") _, out("f9") _);
| ----------- ^^^^^^^^^^^ register `f9` | ----------- ^^^^^^^^^^^ register `f9`
@ -247,7 +223,7 @@ LL | asm!("", out("v9") _, out("f9") _);
| register `v9` | register `v9`
error: register `f10` conflicts with register `v10` error: register `f10` conflicts with register `v10`
--> $DIR/bad-reg.rs:112:32 --> $DIR/bad-reg.rs:154:32
| |
LL | asm!("", out("v10") _, out("f10") _); LL | asm!("", out("v10") _, out("f10") _);
| ------------ ^^^^^^^^^^^^ register `f10` | ------------ ^^^^^^^^^^^^ register `f10`
@ -255,7 +231,7 @@ LL | asm!("", out("v10") _, out("f10") _);
| register `v10` | register `v10`
error: register `f11` conflicts with register `v11` error: register `f11` conflicts with register `v11`
--> $DIR/bad-reg.rs:114:32 --> $DIR/bad-reg.rs:156:32
| |
LL | asm!("", out("v11") _, out("f11") _); LL | asm!("", out("v11") _, out("f11") _);
| ------------ ^^^^^^^^^^^^ register `f11` | ------------ ^^^^^^^^^^^^ register `f11`
@ -263,7 +239,7 @@ LL | asm!("", out("v11") _, out("f11") _);
| register `v11` | register `v11`
error: register `f12` conflicts with register `v12` error: register `f12` conflicts with register `v12`
--> $DIR/bad-reg.rs:116:32 --> $DIR/bad-reg.rs:158:32
| |
LL | asm!("", out("v12") _, out("f12") _); LL | asm!("", out("v12") _, out("f12") _);
| ------------ ^^^^^^^^^^^^ register `f12` | ------------ ^^^^^^^^^^^^ register `f12`
@ -271,7 +247,7 @@ LL | asm!("", out("v12") _, out("f12") _);
| register `v12` | register `v12`
error: register `f13` conflicts with register `v13` error: register `f13` conflicts with register `v13`
--> $DIR/bad-reg.rs:118:32 --> $DIR/bad-reg.rs:160:32
| |
LL | asm!("", out("v13") _, out("f13") _); LL | asm!("", out("v13") _, out("f13") _);
| ------------ ^^^^^^^^^^^^ register `f13` | ------------ ^^^^^^^^^^^^ register `f13`
@ -279,7 +255,7 @@ LL | asm!("", out("v13") _, out("f13") _);
| register `v13` | register `v13`
error: register `f14` conflicts with register `v14` error: register `f14` conflicts with register `v14`
--> $DIR/bad-reg.rs:120:32 --> $DIR/bad-reg.rs:162:32
| |
LL | asm!("", out("v14") _, out("f14") _); LL | asm!("", out("v14") _, out("f14") _);
| ------------ ^^^^^^^^^^^^ register `f14` | ------------ ^^^^^^^^^^^^ register `f14`
@ -287,7 +263,7 @@ LL | asm!("", out("v14") _, out("f14") _);
| register `v14` | register `v14`
error: register `f15` conflicts with register `v15` error: register `f15` conflicts with register `v15`
--> $DIR/bad-reg.rs:122:32 --> $DIR/bad-reg.rs:164:32
| |
LL | asm!("", out("v15") _, out("f15") _); LL | asm!("", out("v15") _, out("f15") _);
| ------------ ^^^^^^^^^^^^ register `f15` | ------------ ^^^^^^^^^^^^ register `f15`
@ -295,13 +271,73 @@ LL | asm!("", out("v15") _, out("f15") _);
| register `v15` | register `v15`
error: invalid register `f16`: unknown register error: invalid register `f16`: unknown register
--> $DIR/bad-reg.rs:125:32 --> $DIR/bad-reg.rs:167:32
| |
LL | asm!("", out("v16") _, out("f16") _); LL | asm!("", out("v16") _, out("f16") _);
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:74:18
|
LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:78:18
|
LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:86:18
|
LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:90:18
|
LL | asm!("", in("v0") b);
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:95:18
|
LL | asm!("", out("v0") b);
| ^^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:100:26
|
LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:104:26
|
LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:108:26
|
LL | asm!("/* {} */", in(vreg) b);
| ^^^^^^^^^^
error: register class `vreg` requires the `vector` target feature
--> $DIR/bad-reg.rs:113:26
|
LL | asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
error: type `i32` cannot be used with this register class error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:63:27 --> $DIR/bad-reg.rs:120:27
| |
LL | asm!("", in("a2") x); LL | asm!("", in("a2") x);
| ^ | ^
@ -309,7 +345,7 @@ LL | asm!("", in("a2") x);
= note: register class `areg` supports these types: = note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:28 --> $DIR/bad-reg.rs:123:28
| |
LL | asm!("", out("a2") x); LL | asm!("", out("a2") x);
| ^ | ^
@ -317,36 +353,12 @@ LL | asm!("", out("a2") x);
= note: register class `areg` supports these types: = note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:69:35 --> $DIR/bad-reg.rs:126:35
| |
LL | asm!("/* {} */", in(areg) x); LL | asm!("/* {} */", in(areg) x);
| ^ | ^
| |
= note: register class `areg` supports these types: = note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class error: aborting due to 54 previous errors
--> $DIR/bad-reg.rs:78:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:81:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:84:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types:
error: aborting due to 51 previous errors

View file

@ -0,0 +1,328 @@
error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:31:18
|
LL | asm!("", out("r11") _);
| ^^^^^^^^^^^^
error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:33:18
|
LL | asm!("", out("r15") _);
| ^^^^^^^^^^^^
error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:35:18
|
LL | asm!("", out("c0") _);
| ^^^^^^^^^^^
error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:37:18
|
LL | asm!("", out("c1") _);
| ^^^^^^^^^^^
error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:39:18
|
LL | asm!("", out("c2") _);
| ^^^^^^^^^^^
error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:41:18
|
LL | asm!("", out("c3") _);
| ^^^^^^^^^^^
error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:43:18
|
LL | asm!("", out("c4") _);
| ^^^^^^^^^^^
error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:45:18
|
LL | asm!("", out("c5") _);
| ^^^^^^^^^^^
error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:47:18
|
LL | asm!("", out("c6") _);
| ^^^^^^^^^^^
error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:49:18
|
LL | asm!("", out("c7") _);
| ^^^^^^^^^^^
error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:51:18
|
LL | asm!("", out("c8") _);
| ^^^^^^^^^^^
error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:53:18
|
LL | asm!("", out("c9") _);
| ^^^^^^^^^^^
error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:55:18
|
LL | asm!("", out("c10") _);
| ^^^^^^^^^^^^
error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:57:18
|
LL | asm!("", out("c11") _);
| ^^^^^^^^^^^^
error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:59:18
|
LL | asm!("", out("c12") _);
| ^^^^^^^^^^^^
error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:61:18
|
LL | asm!("", out("c13") _);
| ^^^^^^^^^^^^
error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:63:18
|
LL | asm!("", out("c14") _);
| ^^^^^^^^^^^^
error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:65:18
|
LL | asm!("", out("c15") _);
| ^^^^^^^^^^^^
error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:67:18
|
LL | asm!("", out("a0") _);
| ^^^^^^^^^^^
error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("a1") _);
| ^^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:120:18
|
LL | asm!("", in("a2") x);
| ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:123:18
|
LL | asm!("", out("a2") x);
| ^^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:126:26
|
LL | asm!("/* {} */", in(areg) x);
| ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:129:26
|
LL | asm!("/* {} */", out(areg) _);
| ^^^^^^^^^^^
error: register `f0` conflicts with register `v0`
--> $DIR/bad-reg.rs:134:31
|
LL | asm!("", out("v0") _, out("f0") _);
| ----------- ^^^^^^^^^^^ register `f0`
| |
| register `v0`
error: register `f1` conflicts with register `v1`
--> $DIR/bad-reg.rs:136:31
|
LL | asm!("", out("v1") _, out("f1") _);
| ----------- ^^^^^^^^^^^ register `f1`
| |
| register `v1`
error: register `f2` conflicts with register `v2`
--> $DIR/bad-reg.rs:138:31
|
LL | asm!("", out("v2") _, out("f2") _);
| ----------- ^^^^^^^^^^^ register `f2`
| |
| register `v2`
error: register `f3` conflicts with register `v3`
--> $DIR/bad-reg.rs:140:31
|
LL | asm!("", out("v3") _, out("f3") _);
| ----------- ^^^^^^^^^^^ register `f3`
| |
| register `v3`
error: register `f4` conflicts with register `v4`
--> $DIR/bad-reg.rs:142:31
|
LL | asm!("", out("v4") _, out("f4") _);
| ----------- ^^^^^^^^^^^ register `f4`
| |
| register `v4`
error: register `f5` conflicts with register `v5`
--> $DIR/bad-reg.rs:144:31
|
LL | asm!("", out("v5") _, out("f5") _);
| ----------- ^^^^^^^^^^^ register `f5`
| |
| register `v5`
error: register `f6` conflicts with register `v6`
--> $DIR/bad-reg.rs:146:31
|
LL | asm!("", out("v6") _, out("f6") _);
| ----------- ^^^^^^^^^^^ register `f6`
| |
| register `v6`
error: register `f7` conflicts with register `v7`
--> $DIR/bad-reg.rs:148:31
|
LL | asm!("", out("v7") _, out("f7") _);
| ----------- ^^^^^^^^^^^ register `f7`
| |
| register `v7`
error: register `f8` conflicts with register `v8`
--> $DIR/bad-reg.rs:150:31
|
LL | asm!("", out("v8") _, out("f8") _);
| ----------- ^^^^^^^^^^^ register `f8`
| |
| register `v8`
error: register `f9` conflicts with register `v9`
--> $DIR/bad-reg.rs:152:31
|
LL | asm!("", out("v9") _, out("f9") _);
| ----------- ^^^^^^^^^^^ register `f9`
| |
| register `v9`
error: register `f10` conflicts with register `v10`
--> $DIR/bad-reg.rs:154:32
|
LL | asm!("", out("v10") _, out("f10") _);
| ------------ ^^^^^^^^^^^^ register `f10`
| |
| register `v10`
error: register `f11` conflicts with register `v11`
--> $DIR/bad-reg.rs:156:32
|
LL | asm!("", out("v11") _, out("f11") _);
| ------------ ^^^^^^^^^^^^ register `f11`
| |
| register `v11`
error: register `f12` conflicts with register `v12`
--> $DIR/bad-reg.rs:158:32
|
LL | asm!("", out("v12") _, out("f12") _);
| ------------ ^^^^^^^^^^^^ register `f12`
| |
| register `v12`
error: register `f13` conflicts with register `v13`
--> $DIR/bad-reg.rs:160:32
|
LL | asm!("", out("v13") _, out("f13") _);
| ------------ ^^^^^^^^^^^^ register `f13`
| |
| register `v13`
error: register `f14` conflicts with register `v14`
--> $DIR/bad-reg.rs:162:32
|
LL | asm!("", out("v14") _, out("f14") _);
| ------------ ^^^^^^^^^^^^ register `f14`
| |
| register `v14`
error: register `f15` conflicts with register `v15`
--> $DIR/bad-reg.rs:164:32
|
LL | asm!("", out("v15") _, out("f15") _);
| ------------ ^^^^^^^^^^^^ register `f15`
| |
| register `v15`
error: invalid register `f16`: unknown register
--> $DIR/bad-reg.rs:167:32
|
LL | asm!("", out("v16") _, out("f16") _);
| ^^^^^^^^^^^^
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:90:27
|
LL | asm!("", in("v0") b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:95:28
|
LL | asm!("", out("v0") b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:108:35
|
LL | asm!("/* {} */", in(vreg) b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:120:27
|
LL | asm!("", in("a2") x);
| ^
|
= note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:123:28
|
LL | asm!("", out("a2") x);
| ^
|
= note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:126:35
|
LL | asm!("/* {} */", in(areg) x);
| ^
|
= note: register class `areg` supports these types:
error: aborting due to 47 previous errors

View file

@ -0,0 +1,489 @@
error: invalid register `r11`: The frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:31:18
|
LL | asm!("", out("r11") _);
| ^^^^^^^^^^^^
error: invalid register `r15`: The stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:33:18
|
LL | asm!("", out("r15") _);
| ^^^^^^^^^^^^
error: invalid register `c0`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:35:18
|
LL | asm!("", out("c0") _);
| ^^^^^^^^^^^
error: invalid register `c1`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:37:18
|
LL | asm!("", out("c1") _);
| ^^^^^^^^^^^
error: invalid register `c2`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:39:18
|
LL | asm!("", out("c2") _);
| ^^^^^^^^^^^
error: invalid register `c3`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:41:18
|
LL | asm!("", out("c3") _);
| ^^^^^^^^^^^
error: invalid register `c4`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:43:18
|
LL | asm!("", out("c4") _);
| ^^^^^^^^^^^
error: invalid register `c5`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:45:18
|
LL | asm!("", out("c5") _);
| ^^^^^^^^^^^
error: invalid register `c6`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:47:18
|
LL | asm!("", out("c6") _);
| ^^^^^^^^^^^
error: invalid register `c7`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:49:18
|
LL | asm!("", out("c7") _);
| ^^^^^^^^^^^
error: invalid register `c8`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:51:18
|
LL | asm!("", out("c8") _);
| ^^^^^^^^^^^
error: invalid register `c9`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:53:18
|
LL | asm!("", out("c9") _);
| ^^^^^^^^^^^
error: invalid register `c10`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:55:18
|
LL | asm!("", out("c10") _);
| ^^^^^^^^^^^^
error: invalid register `c11`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:57:18
|
LL | asm!("", out("c11") _);
| ^^^^^^^^^^^^
error: invalid register `c12`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:59:18
|
LL | asm!("", out("c12") _);
| ^^^^^^^^^^^^
error: invalid register `c13`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:61:18
|
LL | asm!("", out("c13") _);
| ^^^^^^^^^^^^
error: invalid register `c14`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:63:18
|
LL | asm!("", out("c14") _);
| ^^^^^^^^^^^^
error: invalid register `c15`: control registers are reserved by the kernel and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:65:18
|
LL | asm!("", out("c15") _);
| ^^^^^^^^^^^^
error: invalid register `a0`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:67:18
|
LL | asm!("", out("a0") _);
| ^^^^^^^^^^^
error: invalid register `a1`: a0 and a1 are reserved for system use and cannot be used as operands for inline asm
--> $DIR/bad-reg.rs:69:18
|
LL | asm!("", out("a1") _);
| ^^^^^^^^^^^
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:74:18
|
LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:78:18
|
LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:86:18
|
LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:90:18
|
LL | asm!("", in("v0") b);
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:95:18
|
LL | asm!("", out("v0") b);
| ^^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:100:26
|
LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:104:26
|
LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:108:26
|
LL | asm!("/* {} */", in(vreg) b);
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/bad-reg.rs:113:26
|
LL | asm!("/* {} */", out(vreg) _); // requires vector & asm_experimental_reg
| ^^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:120:18
|
LL | asm!("", in("a2") x);
| ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:123:18
|
LL | asm!("", out("a2") x);
| ^^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:126:26
|
LL | asm!("/* {} */", in(areg) x);
| ^^^^^^^^^^
error: register class `areg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:129:26
|
LL | asm!("/* {} */", out(areg) _);
| ^^^^^^^^^^^
error: register `f0` conflicts with register `v0`
--> $DIR/bad-reg.rs:134:31
|
LL | asm!("", out("v0") _, out("f0") _);
| ----------- ^^^^^^^^^^^ register `f0`
| |
| register `v0`
error: register `f1` conflicts with register `v1`
--> $DIR/bad-reg.rs:136:31
|
LL | asm!("", out("v1") _, out("f1") _);
| ----------- ^^^^^^^^^^^ register `f1`
| |
| register `v1`
error: register `f2` conflicts with register `v2`
--> $DIR/bad-reg.rs:138:31
|
LL | asm!("", out("v2") _, out("f2") _);
| ----------- ^^^^^^^^^^^ register `f2`
| |
| register `v2`
error: register `f3` conflicts with register `v3`
--> $DIR/bad-reg.rs:140:31
|
LL | asm!("", out("v3") _, out("f3") _);
| ----------- ^^^^^^^^^^^ register `f3`
| |
| register `v3`
error: register `f4` conflicts with register `v4`
--> $DIR/bad-reg.rs:142:31
|
LL | asm!("", out("v4") _, out("f4") _);
| ----------- ^^^^^^^^^^^ register `f4`
| |
| register `v4`
error: register `f5` conflicts with register `v5`
--> $DIR/bad-reg.rs:144:31
|
LL | asm!("", out("v5") _, out("f5") _);
| ----------- ^^^^^^^^^^^ register `f5`
| |
| register `v5`
error: register `f6` conflicts with register `v6`
--> $DIR/bad-reg.rs:146:31
|
LL | asm!("", out("v6") _, out("f6") _);
| ----------- ^^^^^^^^^^^ register `f6`
| |
| register `v6`
error: register `f7` conflicts with register `v7`
--> $DIR/bad-reg.rs:148:31
|
LL | asm!("", out("v7") _, out("f7") _);
| ----------- ^^^^^^^^^^^ register `f7`
| |
| register `v7`
error: register `f8` conflicts with register `v8`
--> $DIR/bad-reg.rs:150:31
|
LL | asm!("", out("v8") _, out("f8") _);
| ----------- ^^^^^^^^^^^ register `f8`
| |
| register `v8`
error: register `f9` conflicts with register `v9`
--> $DIR/bad-reg.rs:152:31
|
LL | asm!("", out("v9") _, out("f9") _);
| ----------- ^^^^^^^^^^^ register `f9`
| |
| register `v9`
error: register `f10` conflicts with register `v10`
--> $DIR/bad-reg.rs:154:32
|
LL | asm!("", out("v10") _, out("f10") _);
| ------------ ^^^^^^^^^^^^ register `f10`
| |
| register `v10`
error: register `f11` conflicts with register `v11`
--> $DIR/bad-reg.rs:156:32
|
LL | asm!("", out("v11") _, out("f11") _);
| ------------ ^^^^^^^^^^^^ register `f11`
| |
| register `v11`
error: register `f12` conflicts with register `v12`
--> $DIR/bad-reg.rs:158:32
|
LL | asm!("", out("v12") _, out("f12") _);
| ------------ ^^^^^^^^^^^^ register `f12`
| |
| register `v12`
error: register `f13` conflicts with register `v13`
--> $DIR/bad-reg.rs:160:32
|
LL | asm!("", out("v13") _, out("f13") _);
| ------------ ^^^^^^^^^^^^ register `f13`
| |
| register `v13`
error: register `f14` conflicts with register `v14`
--> $DIR/bad-reg.rs:162:32
|
LL | asm!("", out("v14") _, out("f14") _);
| ------------ ^^^^^^^^^^^^ register `f14`
| |
| register `v14`
error: register `f15` conflicts with register `v15`
--> $DIR/bad-reg.rs:164:32
|
LL | asm!("", out("v15") _, out("f15") _);
| ------------ ^^^^^^^^^^^^ register `f15`
| |
| register `v15`
error: invalid register `f16`: unknown register
--> $DIR/bad-reg.rs:167:32
|
LL | asm!("", out("v16") _, out("f16") _);
| ^^^^^^^^^^^^
error[E0658]: type `i64x2` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:74:27
|
LL | asm!("", in("v0") v); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: type `i64x2` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:78:28
|
LL | asm!("", out("v0") v); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: type `i32` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:82:27
|
LL | asm!("", in("v0") x); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: type `i32` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:86:28
|
LL | asm!("", out("v0") x); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:90:27
|
LL | asm!("", in("v0") b);
| ^
|
= note: register class `vreg` supports these types:
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:95:28
|
LL | asm!("", out("v0") b);
| ^
|
= note: register class `vreg` supports these types:
error[E0658]: type `i64x2` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:100:35
|
LL | asm!("/* {} */", in(vreg) v); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: type `i32` cannot be used with this register class in stable
--> $DIR/bad-reg.rs:104:35
|
LL | asm!("/* {} */", in(vreg) x); // requires vector & asm_experimental_reg
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:108:35
|
LL | asm!("/* {} */", in(vreg) b);
| ^
|
= note: register class `vreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:120:27
|
LL | asm!("", in("a2") x);
| ^
|
= note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:123:28
|
LL | asm!("", out("a2") x);
| ^
|
= note: register class `areg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:126:35
|
LL | asm!("/* {} */", in(areg) x);
| ^
|
= note: register class `areg` supports these types:
error: aborting due to 63 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -3,7 +3,7 @@
//@ needs-asm-support //@ needs-asm-support
#![deny(unreachable_code)] #![deny(unreachable_code)]
#![feature(asm_goto)] #![feature(asm_goto, asm_goto_with_outputs)]
use std::arch::asm; use std::arch::asm;
@ -31,10 +31,6 @@ fn goto_jump() {
} }
} }
// asm goto with outputs cause miscompilation in LLVM. UB can be triggered
// when outputs are used inside the label block when optimisation is enabled.
// See: https://github.com/llvm/llvm-project/issues/74483
/*
fn goto_out_fallthrough() { fn goto_out_fallthrough() {
unsafe { unsafe {
let mut out: usize; let mut out: usize;
@ -68,7 +64,57 @@ fn goto_out_jump() {
assert!(value); assert!(value);
} }
} }
*/
fn goto_out_jump_noreturn() {
unsafe {
let mut value = false;
let mut out: usize;
asm!(
"lea {}, [{} + 1]",
"jmp {}",
out(reg) out,
in(reg) 0x12345678usize,
label {
value = true;
assert_eq!(out, 0x12345679);
},
options(noreturn)
);
assert!(value);
}
}
// asm goto with outputs cause miscompilation in LLVM when multiple outputs are present.
// The code sample below is adapted from https://github.com/llvm/llvm-project/issues/74483
// and does not work with `-C opt-level=0`
#[expect(unused)]
fn goto_multi_out() {
#[inline(never)]
#[allow(unused)]
fn goto_multi_out(a: usize, b: usize) -> usize {
let mut x: usize;
let mut y: usize;
let mut z: usize;
unsafe {
core::arch::asm!(
"mov {x}, {a}",
"test {a}, {a}",
"jnz {label1}",
"/* {y} {z} {b} {label2} */",
x = out(reg) x,
y = out(reg) y,
z = out(reg) z,
a = in(reg) a,
b = in(reg) b,
label1 = label { return x },
label2 = label { return 1 },
);
0
}
}
assert_eq!(goto_multi_out(11, 22), 11);
}
fn goto_noreturn() { fn goto_noreturn() {
unsafe { unsafe {
@ -102,8 +148,10 @@ fn goto_noreturn_diverge() {
fn main() { fn main() {
goto_fallthough(); goto_fallthough();
goto_jump(); goto_jump();
// goto_out_fallthrough(); goto_out_fallthrough();
// goto_out_jump(); goto_out_jump();
goto_out_jump_noreturn();
// goto_multi_out();
goto_noreturn(); goto_noreturn();
goto_noreturn_diverge(); goto_noreturn_diverge();
} }

View file

@ -1,5 +1,5 @@
warning: unreachable statement warning: unreachable statement
--> $DIR/goto.rs:97:9 --> $DIR/goto.rs:143:9
| |
LL | / asm!( LL | / asm!(
LL | | "jmp {}", LL | | "jmp {}",
@ -13,7 +13,7 @@ LL | unreachable!();
| ^^^^^^^^^^^^^^ unreachable statement | ^^^^^^^^^^^^^^ unreachable statement
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/goto.rs:87:8 --> $DIR/goto.rs:133:8
| |
LL | #[warn(unreachable_code)] LL | #[warn(unreachable_code)]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^

View file

@ -0,0 +1,23 @@
//@ needs-asm-support
//@ compile-flags: --target s390x-unknown-linux-gnu
//@ needs-llvm-components: systemz
#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "rlib"]
#![no_core]
#[rustc_builtin_macro]
macro_rules! asm {
() => {};
}
#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}
unsafe fn main() {
asm!("", in("v0") 0);
//~^ ERROR register class `vreg` can only be used as a clobber in stable
//~| ERROR type `i32` cannot be used with this register class
}

View file

@ -0,0 +1,23 @@
error[E0658]: register class `vreg` can only be used as a clobber in stable
--> $DIR/feature-gate-asm_experimental_reg.rs:20:14
|
LL | asm!("", in("v0") 0);
| ^^^^^^^^^^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0658]: type `i32` cannot be used with this register class in stable
--> $DIR/feature-gate-asm_experimental_reg.rs:20:23
|
LL | asm!("", in("v0") 0);
| ^
|
= note: see issue #133416 <https://github.com/rust-lang/rust/issues/133416> for more information
= help: add `#![feature(asm_experimental_reg)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,13 @@
//@ only-x86_64
#![feature(asm_goto)]
use std::arch::asm;
fn main() {
let mut _out: u64;
unsafe {
asm!("mov {}, 1", "jmp {}", out(reg) _out, label {});
//~^ ERROR using both label and output operands for inline assembly is unstable
}
}

View file

@ -0,0 +1,13 @@
error[E0658]: using both label and output operands for inline assembly is unstable
--> $DIR/feature-gate-asm_goto_with_outputs.rs:10:52
|
LL | asm!("mov {}, 1", "jmp {}", out(reg) _out, label {});
| ^^^^^^^^
|
= note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information
= help: add `#![feature(asm_goto_with_outputs)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -428,8 +428,14 @@ trigger_files = [
"triagebot.toml", "triagebot.toml",
"rustfmt.toml", "rustfmt.toml",
"LICENSES", "LICENSES",
"COPYRIGHT",
"LICENSE-APACHE",
"LICENSE-MIT",
"CODE_OF_CONDUCT.md",
"README.md", "README.md",
"CONTRIBUTING.md", "CONTRIBUTING.md",
"INSTALL.md",
"REUSE.toml",
".reuse", ".reuse",
".mailmap", ".mailmap",
".git-blame-ignore-revs", ".git-blame-ignore-revs",