Auto merge of #122980 - workingjubilee:rollup-r5i1rke, r=workingjubilee

Rollup of 7 pull requests

Successful merges:

 - #120419 (Expand sys/os for UEFI)
 - #121940 (Mention Register Size in `#[warn(asm_sub_register)]`)
 - #122762 (fix typo of endianness)
 - #122797 (Fix compile of wasm64-unknown-unknown target)
 - #122875 (CFI: Support self_cell-like recursion)
 - #122879 (CFI: Strip auto traits off Virtual calls)
 - #122969 (Simplify an iterator search in borrowck diag)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-03-24 09:04:01 +00:00
commit 4a52e9cc2a
49 changed files with 484 additions and 237 deletions

View File

@ -4,7 +4,6 @@ use crate::session_diagnostics::{
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
};
use itertools::Itertools;
use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, Namespace};
@ -226,16 +225,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
} else {
if autoderef_index.is_none() {
autoderef_index =
match place.projection.into_iter().rev().find_position(|elem| {
!matches!(
elem,
ProjectionElem::Deref | ProjectionElem::Downcast(..)
)
}) {
Some((index, _)) => Some(place.projection.len() - index),
None => Some(0),
};
autoderef_index = match place.projection.iter().rposition(|elem| {
!matches!(
elem,
ProjectionElem::Deref | ProjectionElem::Downcast(..)
)
}) {
Some(index) => Some(index + 1),
None => Some(0),
};
}
if index >= autoderef_index.unwrap() {
buf.insert(0, '*');

View File

@ -541,7 +541,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
let builtin_unreachable: RValue<'gcc> = unsafe {
std::mem::transmute(builtin_unreachable)
};
self.call(self.type_void(), None, None, builtin_unreachable, &[], None);
self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None);
}
// Write results to outputs.

View File

@ -25,7 +25,7 @@ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
TyAndLayout,
};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Instance};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_target::abi::{
@ -592,12 +592,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
then: Block<'gcc>,
catch: Block<'gcc>,
_funclet: Option<&Funclet>,
instance: Option<Instance<'tcx>>,
) -> RValue<'gcc> {
let try_block = self.current_func().new_block("try");
let current_block = self.block.clone();
self.block = try_block;
let call = self.call(typ, fn_attrs, None, func, args, None); // TODO(antoyo): use funclet here?
let call = self.call(typ, fn_attrs, None, func, args, None, instance); // TODO(antoyo): use funclet here?
self.block = current_block;
let return_value =
@ -1667,6 +1668,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
func: RValue<'gcc>,
args: &[RValue<'gcc>],
funclet: Option<&Funclet>,
_instance: Option<Instance<'tcx>>,
) -> RValue<'gcc> {
// FIXME(antoyo): remove when having a proper API.
let gcc_func = unsafe { std::mem::transmute(func) };

View File

@ -133,6 +133,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
func,
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None,
None,
)
}
sym::likely => self.expect(args[0].immediate(), true),
@ -401,7 +402,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn abort(&mut self) {
let func = self.context.get_builtin_function("abort");
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
self.call(self.type_void(), None, None, func, &[], None);
self.call(self.type_void(), None, None, func, &[], None, None);
}
fn assume(&mut self, value: Self::Value) {
@ -1103,7 +1104,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
dest: RValue<'gcc>,
) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
bx.call(bx.type_void(), None, None, try_func, &[data], None);
bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
let ret_align = bx.tcx.data_layout.i32_align.abi;
@ -1177,21 +1178,21 @@ fn codegen_gnu_try<'gcc>(
let zero = bx.cx.context.new_rvalue_zero(bx.int_type);
let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None);
bx.ret(bx.const_i32(1));
// NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not
// generate a try/catch.
// FIXME(antoyo): add a check in the libgccjit API to prevent this.
bx.switch_to_block(current_block);
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
});
let func = unsafe { std::mem::transmute(func) };
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}

View File

@ -466,11 +466,11 @@ pub(crate) fn inline_asm_call<'ll>(
let call = if !labels.is_empty() {
assert!(catch_funclet.is_none());
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None)
bx.callbr(fty, None, None, v, inputs, dest.unwrap(), labels, None, None)
} else if let Some((catch, funclet)) = catch_funclet {
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet)
bx.invoke(fty, None, None, v, inputs, dest.unwrap(), catch, funclet, None)
} else {
bx.call(fty, None, None, v, inputs, None)
bx.call(fty, None, None, v, inputs, None, None)
};
// Store mark in a metadata node so we can map LLVM errors

View File

@ -19,9 +19,12 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_span::Span;
use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
use rustc_symbol_mangling::typeid::{
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
TypeIdOptions,
};
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
use smallvec::SmallVec;
@ -221,6 +224,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
then: &'ll BasicBlock,
catch: &'ll BasicBlock,
funclet: Option<&Funclet<'ll>>,
instance: Option<Instance<'tcx>>,
) -> &'ll Value {
debug!("invoke {:?} with args ({:?})", llfn, args);
@ -233,10 +237,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
// Emit CFI pointer type membership test
self.cfi_type_test(fn_attrs, fn_abi, llfn);
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
// Emit KCFI operand bundle
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
if let Some(kcfi_bundle) = kcfi_bundle {
bundles.push(kcfi_bundle);
@ -1231,6 +1235,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
llfn: &'ll Value,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
instance: Option<Instance<'tcx>>,
) -> &'ll Value {
debug!("call {:?} with args ({:?})", llfn, args);
@ -1243,10 +1248,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
// Emit CFI pointer type membership test
self.cfi_type_test(fn_attrs, fn_abi, llfn);
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
// Emit KCFI operand bundle
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
if let Some(kcfi_bundle) = kcfi_bundle {
bundles.push(kcfi_bundle);
@ -1468,7 +1473,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
let (ty, f) = self.cx.get_intrinsic(intrinsic);
self.call(ty, None, None, f, args, None)
self.call(ty, None, None, f, args, None, None)
}
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
@ -1526,7 +1531,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
format!("llvm.{instr}.sat.i{int_width}.f{float_width}")
};
let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None)
self.call(self.type_func(&[src_ty], dest_ty), None, None, f, &[val], None, None)
}
pub(crate) fn landing_pad(
@ -1554,6 +1559,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
default_dest: &'ll BasicBlock,
indirect_dest: &[&'ll BasicBlock],
funclet: Option<&Funclet<'ll>>,
instance: Option<Instance<'tcx>>,
) -> &'ll Value {
debug!("invoke {:?} with args ({:?})", llfn, args);
@ -1566,10 +1572,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
}
// Emit CFI pointer type membership test
self.cfi_type_test(fn_attrs, fn_abi, llfn);
self.cfi_type_test(fn_attrs, fn_abi, instance, llfn);
// Emit KCFI operand bundle
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, instance, llfn);
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
if let Some(kcfi_bundle) = kcfi_bundle {
bundles.push(kcfi_bundle);
@ -1601,6 +1607,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
&mut self,
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
instance: Option<Instance<'tcx>>,
llfn: &'ll Value,
) {
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
@ -1622,7 +1629,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
}
let typeid = typeid_for_fnabi(self.tcx, fn_abi, options);
let typeid = if let Some(instance) = instance {
typeid_for_instance(self.tcx, &instance, options)
} else {
typeid_for_fnabi(self.tcx, fn_abi, options)
};
let typeid_metadata = self.cx.typeid_metadata(typeid).unwrap();
// Test whether the function pointer is associated with the type identifier.
@ -1644,6 +1655,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
&mut self,
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
instance: Option<Instance<'tcx>>,
llfn: &'ll Value,
) -> Option<llvm::OperandBundleDef<'ll>> {
let is_indirect_call = unsafe { llvm::LLVMRustIsNonGVFunctionPointerTy(llfn) };
@ -1665,7 +1677,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
options.insert(TypeIdOptions::NORMALIZE_INTEGERS);
}
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
let kcfi_typeid = if let Some(instance) = instance {
kcfi_typeid_for_instance(self.tcx, &instance, options)
} else {
kcfi_typeid_for_fnabi(self.tcx, fn_abi, options)
};
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
} else {
None

View File

@ -181,6 +181,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
simple_fn,
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None,
Some(instance),
)
}
sym::likely => {
@ -539,7 +540,7 @@ fn catch_unwind_intrinsic<'ll>(
) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.call(try_func_ty, None, None, try_func, &[data], None);
bx.call(try_func_ty, None, None, try_func, &[data], None, None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
let ret_align = bx.tcx().data_layout.i32_align.abi;
@ -640,7 +641,7 @@ fn codegen_msvc_try<'ll>(
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let slot = bx.alloca(bx.type_ptr(), ptr_align);
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
bx.switch_to_block(normal);
bx.ret(bx.const_i32(0));
@ -684,7 +685,7 @@ fn codegen_msvc_try<'ll>(
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
let ptr = bx.load(bx.type_ptr(), slot, ptr_align);
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None);
bx.catch_ret(&funclet, caught);
// The flag value of 64 indicates a "catch-all".
@ -692,7 +693,7 @@ fn codegen_msvc_try<'ll>(
let flags = bx.const_i32(64);
let null = bx.const_null(bx.type_ptr());
let funclet = bx.catch_pad(cs, &[null, flags, null]);
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet));
bx.call(catch_ty, None, None, catch_func, &[data, null], Some(&funclet), None);
bx.catch_ret(&funclet, caught);
bx.switch_to_block(caught);
@ -701,7 +702,7 @@ fn codegen_msvc_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@ -750,7 +751,7 @@ fn codegen_wasm_try<'ll>(
// }
//
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None, None);
bx.switch_to_block(normal);
bx.ret(bx.const_i32(0));
@ -766,7 +767,7 @@ fn codegen_wasm_try<'ll>(
let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[funclet.cleanuppad()]);
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet));
bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet), None);
bx.catch_ret(&funclet, caught);
bx.switch_to_block(caught);
@ -775,7 +776,7 @@ fn codegen_wasm_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@ -818,7 +819,7 @@ fn codegen_gnu_try<'ll>(
let data = llvm::get_param(bx.llfn(), 1);
let catch_func = llvm::get_param(bx.llfn(), 2);
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
bx.switch_to_block(then);
bx.ret(bx.const_i32(0));
@ -836,13 +837,13 @@ fn codegen_gnu_try<'ll>(
bx.add_clause(vals, tydesc);
let ptr = bx.extract_value(vals, 0);
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None);
bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None);
bx.ret(bx.const_i32(1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@ -882,7 +883,7 @@ fn codegen_emcc_try<'ll>(
let data = llvm::get_param(bx.llfn(), 1);
let catch_func = llvm::get_param(bx.llfn(), 2);
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None);
bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None);
bx.switch_to_block(then);
bx.ret(bx.const_i32(0));
@ -920,13 +921,13 @@ fn codegen_emcc_try<'ll>(
bx.store(is_rust_panic, catch_data_1, i8_align);
let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void());
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None);
bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None, None);
bx.ret(bx.const_i32(1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None);
let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@ -1439,6 +1440,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None,
None,
);
Ok(c)
}
@ -1607,6 +1609,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&[args[1].immediate(), alignment, mask, args[0].immediate()],
None,
None,
);
return Ok(v);
}
@ -1706,6 +1709,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&[args[1].immediate(), alignment, mask, args[2].immediate()],
None,
None,
);
return Ok(v);
}
@ -1799,6 +1803,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&[args[2].immediate(), args[1].immediate(), alignment, mask],
None,
None,
);
return Ok(v);
}
@ -1904,6 +1909,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&[args[0].immediate(), args[1].immediate(), alignment, mask],
None,
None,
);
return Ok(v);
}
@ -2352,11 +2358,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
f,
&[args[0].immediate(), bx.const_int(bx.type_i1(), 0)],
None,
None,
))
} else {
let fn_ty = bx.type_func(&[vec_ty], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
Ok(bx.call(fn_ty, None, None, f, &[args[0].immediate()], None))
Ok(bx.call(fn_ty, None, None, f, &[args[0].immediate()], None, None))
};
}
@ -2409,7 +2416,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
let v = bx.call(fn_ty, None, None, f, &[lhs, rhs], None);
let v = bx.call(fn_ty, None, None, f, &[lhs, rhs], None, None);
return Ok(v);
}

View File

@ -462,27 +462,34 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let ptr_ty = cx.type_ptr();
let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx);
let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
let (start_fn, start_ty, args, instance) = if let EntryFnType::Main { sigpipe } = entry_type
{
let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
let start_fn = cx.get_fn_addr(ty::Instance::expect_resolve(
let start_instance = ty::Instance::expect_resolve(
cx.tcx(),
ty::ParamEnv::reveal_all(),
start_def_id,
cx.tcx().mk_args(&[main_ret_ty.into()]),
));
);
let start_fn = cx.get_fn_addr(start_instance);
let i8_ty = cx.type_i8();
let arg_sigpipe = bx.const_u8(sigpipe);
let start_ty = cx.type_func(&[cx.val_ty(rust_main), isize_ty, ptr_ty, i8_ty], isize_ty);
(start_fn, start_ty, vec![rust_main, arg_argc, arg_argv, arg_sigpipe])
(
start_fn,
start_ty,
vec![rust_main, arg_argc, arg_argv, arg_sigpipe],
Some(start_instance),
)
} else {
debug!("using user-defined start fn");
let start_ty = cx.type_func(&[isize_ty, ptr_ty], isize_ty);
(rust_main, start_ty, vec![arg_argc, arg_argv])
(rust_main, start_ty, vec![arg_argc, arg_argv], None)
};
let result = bx.call(start_ty, None, None, start_fn, &args, None);
let result = bx.call(start_ty, None, None, start_fn, &args, None, instance);
if cx.sess().target.os.contains("uefi") {
bx.ret(result);
} else {

View File

@ -232,6 +232,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
ret_llbb,
unwind_block,
self.funclet(fx),
instance,
);
if fx.mir[self.bb].is_cleanup {
bx.apply_attrs_to_cleanup_callsite(invokeret);
@ -247,7 +248,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
}
MergingSucc::False
} else {
let llret = bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx));
let llret =
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, llargs, self.funclet(fx), instance);
if fx.mir[self.bb].is_cleanup {
bx.apply_attrs_to_cleanup_callsite(llret);
}
@ -502,7 +504,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let ty = location.ty(self.mir, bx.tcx()).ty;
let ty = self.monomorphize(ty);
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
let instance = drop_fn.clone();
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
// we don't actually need to drop anything.
@ -518,7 +519,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args1 = [place.llval];
&args1[..]
};
let (drop_fn, fn_abi) =
let (drop_fn, fn_abi, drop_instance) =
match ty.kind() {
// FIXME(eddyb) perhaps move some of this logic into
// `Instance::resolve_drop_in_place`?
@ -550,6 +551,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
.get_fn(bx, vtable, ty, fn_abi),
fn_abi,
virtual_drop,
)
}
ty::Dynamic(_, _, ty::DynStar) => {
@ -592,9 +594,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
.get_fn(bx, meta.immediate(), ty, fn_abi),
fn_abi,
virtual_drop,
)
}
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
_ => (
bx.get_fn_addr(drop_fn),
bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
drop_fn,
),
};
helper.do_call(
self,
@ -605,7 +612,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
Some((ReturnDest::Nothing, target)),
unwind,
&[],
Some(instance),
Some(drop_instance),
mergeable_succ,
)
}
@ -1699,7 +1706,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
let fn_ty = bx.fn_decl_backend_type(fn_abi);
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref());
let llret = bx.call(fn_ty, None, Some(fn_abi), fn_ptr, &[], funclet.as_ref(), None);
bx.apply_attrs_to_cleanup_callsite(llret);
}

View File

@ -709,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
None
};
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None)
bx.call(fn_ty, fn_attrs, Some(fn_abi), fn_ptr, &[], None, Some(instance))
} else {
bx.get_static(def_id)
};

View File

@ -70,7 +70,15 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// (But we are in good company, this code is duplicated plenty of times.)
let fn_ty = bx.fn_decl_backend_type(fn_abi);
bx.call(fn_ty, /* fn_attrs */ None, Some(fn_abi), llfn, &[msg.0, msg.1], None);
bx.call(
fn_ty,
/* fn_attrs */ None,
Some(fn_abi),
llfn,
&[msg.0, msg.1],
None,
None,
);
// This function does not return so we can now return whatever we want.
let size = bx.const_usize(layout.size.bytes());

View File

@ -17,7 +17,7 @@ use crate::MemFlags;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_middle::ty::{Instance, Ty};
use rustc_session::config::OptLevel;
use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
@ -82,6 +82,7 @@ pub trait BuilderMethods<'a, 'tcx>:
then: Self::BasicBlock,
catch: Self::BasicBlock,
funclet: Option<&Self::Funclet>,
instance: Option<Instance<'tcx>>,
) -> Self::Value;
fn unreachable(&mut self);
@ -389,6 +390,7 @@ pub trait BuilderMethods<'a, 'tcx>:
llfn: Self::Value,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
instance: Option<Instance<'tcx>>,
) -> Self::Value;
fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;

View File

@ -6,7 +6,9 @@ use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::Symbol;
use rustc_target::abi::FieldIdx;
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
use rustc_target::asm::{
InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType, ModifierInfo,
};
pub struct InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
@ -251,8 +253,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
// Check whether a modifier is suggested for using this type.
if let Some((suggested_modifier, suggested_result)) =
reg_class.suggest_modifier(asm_arch, asm_ty)
if let Some(ModifierInfo {
modifier: suggested_modifier,
result: suggested_result,
size: suggested_size,
}) = reg_class.suggest_modifier(asm_arch, asm_ty)
{
// Search for any use of this operand without a modifier and emit
// the suggestion for them.
@ -266,8 +271,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
}
if !spans.is_empty() {
let (default_modifier, default_result) =
reg_class.default_modifier(asm_arch).unwrap();
let ModifierInfo {
modifier: default_modifier,
result: default_result,
size: default_size,
} = reg_class.default_modifier(asm_arch).unwrap();
self.tcx.node_span_lint(
lint::builtin::ASM_SUB_REGISTER,
expr.hir_id,
@ -276,10 +284,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|lint| {
lint.span_label(expr.span, "for this argument");
lint.help(format!(
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}` (for {suggested_size}-bit values)",
));
lint.help(format!(
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}` (for {default_size}-bit values)",
));
},
);

View File

@ -36,7 +36,7 @@ pub fn typeid_for_instance<'tcx>(
instance: &Instance<'tcx>,
options: TypeIdOptions,
) -> String {
typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options)
typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options)
}
/// Returns a KCFI type metadata identifier for the specified FnAbi.
@ -61,6 +61,6 @@ pub fn kcfi_typeid_for_instance<'tcx>(
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
let mut hash: XxHash64 = Default::default();
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options).as_bytes());
hash.finish() as u32
}

View File

@ -178,14 +178,14 @@ fn encode_fnsig<'tcx>(
// Encode the return type
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
.unwrap_or_else(|| bug!("encode_fnsig: invalid option(s) `{:?}`", options.bits()));
let ty = transform_ty(tcx, fn_sig.output(), transform_ty_options);
let ty = transform_ty(tcx, fn_sig.output(), &mut Vec::new(), transform_ty_options);
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
// Encode the parameter types
let tys = fn_sig.inputs();
if !tys.is_empty() {
for ty in tys {
let ty = transform_ty(tcx, *ty, transform_ty_options);
let ty = transform_ty(tcx, *ty, &mut Vec::new(), transform_ty_options);
s.push_str(&encode_ty(tcx, ty, dict, encode_ty_options));
}
@ -767,11 +767,12 @@ fn transform_predicates<'tcx>(
fn transform_args<'tcx>(
tcx: TyCtxt<'tcx>,
args: GenericArgsRef<'tcx>,
parents: &mut Vec<Ty<'tcx>>,
options: TransformTyOptions,
) -> GenericArgsRef<'tcx> {
let args = args.iter().map(|arg| match arg.unpack() {
GenericArgKind::Type(ty) if ty.is_c_void(tcx) => Ty::new_unit(tcx).into(),
GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
GenericArgKind::Type(ty) => transform_ty(tcx, ty, parents, options).into(),
_ => arg,
});
tcx.mk_args_from_iter(args)
@ -781,9 +782,12 @@ fn transform_args<'tcx>(
// c_void types into unit types unconditionally, generalizes pointers if
// TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
// TransformTyOptions::NORMALIZE_INTEGERS option is set.
fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptions) -> Ty<'tcx> {
let mut ty = ty;
fn transform_ty<'tcx>(
tcx: TyCtxt<'tcx>,
mut ty: Ty<'tcx>,
parents: &mut Vec<Ty<'tcx>>,
options: TransformTyOptions,
) -> Ty<'tcx> {
match ty.kind() {
ty::Float(..) | ty::Str | ty::Never | ty::Foreign(..) | ty::CoroutineWitness(..) => {}
@ -843,17 +847,20 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
_ if ty.is_unit() => {}
ty::Tuple(tys) => {
ty = Ty::new_tup_from_iter(tcx, tys.iter().map(|ty| transform_ty(tcx, ty, options)));
ty = Ty::new_tup_from_iter(
tcx,
tys.iter().map(|ty| transform_ty(tcx, ty, parents, options)),
);
}
ty::Array(ty0, len) => {
let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, options), len);
ty = Ty::new_array(tcx, transform_ty(tcx, *ty0, parents, options), len);
}
ty::Slice(ty0) => {
ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, options));
ty = Ty::new_slice(tcx, transform_ty(tcx, *ty0, parents, options));
}
ty::Adt(adt_def, args) => {
@ -862,7 +869,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
} else if options.contains(TransformTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c()
{
ty = Ty::new_adt(tcx, *adt_def, ty::List::empty());
} else if adt_def.repr().transparent() && adt_def.is_struct() {
} else if adt_def.repr().transparent() && adt_def.is_struct() && !parents.contains(&ty)
{
// Don't transform repr(transparent) types with an user-defined CFI encoding to
// preserve the user-defined CFI encoding.
if let Some(_) = tcx.get_attr(adt_def.did(), sym::cfi_encoding) {
@ -881,38 +889,48 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
// Generalize any repr(transparent) user-defined type that is either a pointer
// or reference, and either references itself or any other type that contains or
// references itself, to avoid a reference cycle.
// If the self reference is not through a pointer, for example, due
// to using `PhantomData`, need to skip normalizing it if we hit it again.
parents.push(ty);
if ty0.is_any_ptr() && ty0.contains(ty) {
ty = transform_ty(
tcx,
ty0,
parents,
options | TransformTyOptions::GENERALIZE_POINTERS,
);
} else {
ty = transform_ty(tcx, ty0, options);
ty = transform_ty(tcx, ty0, parents, options);
}
parents.pop();
} else {
// Transform repr(transparent) types without non-ZST field into ()
ty = Ty::new_unit(tcx);
}
} else {
ty = Ty::new_adt(tcx, *adt_def, transform_args(tcx, args, options));
ty = Ty::new_adt(tcx, *adt_def, transform_args(tcx, args, parents, options));
}
}
ty::FnDef(def_id, args) => {
ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, options));
ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, parents, options));
}
ty::Closure(def_id, args) => {
ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options));
ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, parents, options));
}
ty::CoroutineClosure(def_id, args) => {
ty = Ty::new_coroutine_closure(tcx, *def_id, transform_args(tcx, args, options));
ty = Ty::new_coroutine_closure(
tcx,
*def_id,
transform_args(tcx, args, parents, options),
);
}
ty::Coroutine(def_id, args) => {
ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options));
ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, parents, options));
}
ty::Ref(region, ty0, ..) => {
@ -924,9 +942,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
}
} else {
if ty.is_mutable_ptr() {
ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options));
ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, parents, options));
} else {
ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options));
ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, parents, options));
}
}
}
@ -940,9 +958,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
}
} else {
if ty.is_mutable_ptr() {
ty = Ty::new_mut_ptr(tcx, transform_ty(tcx, *ptr_ty, options));
ty = Ty::new_mut_ptr(tcx, transform_ty(tcx, *ptr_ty, parents, options));
} else {
ty = Ty::new_imm_ptr(tcx, transform_ty(tcx, *ptr_ty, options));
ty = Ty::new_imm_ptr(tcx, transform_ty(tcx, *ptr_ty, parents, options));
}
}
}
@ -955,9 +973,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
.skip_binder()
.inputs()
.iter()
.map(|ty| transform_ty(tcx, *ty, options))
.map(|ty| transform_ty(tcx, *ty, parents, options))
.collect();
let output = transform_ty(tcx, fn_sig.skip_binder().output(), options);
let output = transform_ty(tcx, fn_sig.skip_binder().output(), parents, options);
ty = Ty::new_fn_ptr(
tcx,
ty::Binder::bind_with_vars(
@ -987,6 +1005,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
ty = transform_ty(
tcx,
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty),
parents,
options,
);
}
@ -1037,7 +1056,7 @@ pub fn typeid_for_fnabi<'tcx>(
// Encode the return type
let transform_ty_options = TransformTyOptions::from_bits(options.bits())
.unwrap_or_else(|| bug!("typeid_for_fnabi: invalid option(s) `{:?}`", options.bits()));
let ty = transform_ty(tcx, fn_abi.ret.layout.ty, transform_ty_options);
let ty = transform_ty(tcx, fn_abi.ret.layout.ty, &mut Vec::new(), transform_ty_options);
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
// Encode the parameter types
@ -1049,7 +1068,7 @@ pub fn typeid_for_fnabi<'tcx>(
let mut pushed_arg = false;
for arg in fn_abi.args.iter().filter(|arg| arg.mode != PassMode::Ignore) {
pushed_arg = true;
let ty = transform_ty(tcx, arg.layout.ty, transform_ty_options);
let ty = transform_ty(tcx, arg.layout.ty, &mut Vec::new(), transform_ty_options);
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
}
if !pushed_arg {
@ -1062,7 +1081,8 @@ pub fn typeid_for_fnabi<'tcx>(
if fn_abi.args[n].mode == PassMode::Ignore {
continue;
}
let ty = transform_ty(tcx, fn_abi.args[n].layout.ty, transform_ty_options);
let ty =
transform_ty(tcx, fn_abi.args[n].layout.ty, &mut Vec::new(), transform_ty_options);
typeid.push_str(&encode_ty(tcx, ty, &mut dict, encode_ty_options));
}
@ -1088,11 +1108,15 @@ pub fn typeid_for_fnabi<'tcx>(
/// vendor extended type qualifiers and types for Rust types that are not used at the FFI boundary.
pub fn typeid_for_instance<'tcx>(
tcx: TyCtxt<'tcx>,
instance: &Instance<'tcx>,
mut instance: Instance<'tcx>,
options: TypeIdOptions,
) -> String {
if matches!(instance.def, ty::InstanceDef::Virtual(..)) {
instance.args = strip_receiver_auto(tcx, instance.args)
}
let fn_abi = tcx
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, ty::List::empty())))
.fn_abi_of_instance(tcx.param_env(instance.def_id()).and((instance, ty::List::empty())))
.unwrap_or_else(|instance| {
bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance)
});
@ -1138,3 +1162,23 @@ pub fn typeid_for_instance<'tcx>(
typeid_for_fnabi(tcx, fn_abi, options)
}
fn strip_receiver_auto<'tcx>(
tcx: TyCtxt<'tcx>,
args: ty::GenericArgsRef<'tcx>,
) -> ty::GenericArgsRef<'tcx> {
let ty = args.type_at(0);
let ty::Dynamic(preds, lifetime, kind) = ty.kind() else {
bug!("Tried to strip auto traits from non-dynamic type {ty}");
};
let filtered_preds =
if preds.principal().is_some() {
tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| {
!matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..))
}))
} else {
ty::List::empty()
};
let new_rcvr = Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind);
tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1))
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic;
@ -27,32 +27,28 @@ impl AArch64InlineAsmRegClass {
None
}
pub fn suggest_modifier(
self,
_arch: InlineAsmArch,
ty: InlineAsmType,
) -> Option<(char, &'static str)> {
pub fn suggest_modifier(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option<ModifierInfo> {
match self {
Self::reg => match ty.size().bits() {
64 => None,
_ => Some(('w', "w0")),
_ => Some(('w', "w0", 32).into()),
},
Self::vreg | Self::vreg_low16 => match ty.size().bits() {
8 => Some(('b', "b0")),
16 => Some(('h', "h0")),
32 => Some(('s', "s0")),
64 => Some(('d', "d0")),
128 => Some(('q', "q0")),
8 => Some(('b', "b0", 8).into()),
16 => Some(('h', "h0", 16).into()),
32 => Some(('s', "s0", 32).into()),
64 => Some(('d', "d0", 64).into()),
128 => Some(('q', "q0", 128).into()),
_ => None,
},
Self::preg => None,
}
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
match self {
Self::reg => Some(('x', "x0")),
Self::vreg | Self::vreg_low16 => Some(('v', "v0")),
Self::reg => Some(('x', "x0", 64).into()),
Self::vreg | Self::vreg_low16 => Some(('v', "v0", 128).into()),
Self::preg => None,
}
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic;
@ -35,11 +35,11 @@ impl ArmInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -29,11 +29,11 @@ impl AvrInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -23,11 +23,11 @@ impl BpfInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -23,11 +23,11 @@ impl CSKYInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -22,11 +22,11 @@ impl HexagonInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -23,11 +23,11 @@ impl LoongArchInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -24,11 +24,11 @@ impl M68kInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -23,11 +23,11 @@ impl MipsInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -6,6 +6,18 @@ use rustc_span::Symbol;
use std::fmt;
use std::str::FromStr;
pub struct ModifierInfo {
pub modifier: char,
pub result: &'static str,
pub size: u64,
}
impl From<(char, &'static str, u64)> for ModifierInfo {
fn from((modifier, result, size): (char, &'static str, u64)) -> Self {
Self { modifier, result, size }
}
}
macro_rules! def_reg_class {
($arch:ident $arch_regclass:ident {
$(
@ -512,11 +524,7 @@ impl InlineAsmRegClass {
/// Such suggestions are useful if a type smaller than the full register
/// size is used and a modifier can be used to point to the subregister of
/// the correct size.
pub fn suggest_modifier(
self,
arch: InlineAsmArch,
ty: InlineAsmType,
) -> Option<(char, &'static str)> {
pub fn suggest_modifier(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<ModifierInfo> {
match self {
Self::X86(r) => r.suggest_modifier(arch, ty),
Self::Arm(r) => r.suggest_modifier(arch, ty),
@ -545,7 +553,7 @@ impl InlineAsmRegClass {
/// This is only needed when the register class can suggest a modifier, so
/// that the user can be shown how to get the default behavior without a
/// warning.
pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, arch: InlineAsmArch) -> Option<ModifierInfo> {
match self {
Self::X86(r) => r.default_modifier(arch),
Self::Arm(r) => r.default_modifier(arch),

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -22,11 +22,11 @@ impl Msp430InlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
@ -23,11 +23,11 @@ impl NvptxInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -26,11 +26,11 @@ impl PowerPCInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic;
@ -26,11 +26,11 @@ impl RiscVInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;
@ -24,11 +24,11 @@ impl S390xInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
@ -21,11 +21,11 @@ impl SpirVInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
@ -21,11 +21,11 @@ impl WasmInlineAsmRegClass {
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
) -> Option<ModifierInfo> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
None
}

View File

@ -1,4 +1,4 @@
use super::{InlineAsmArch, InlineAsmType};
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
use crate::spec::{RelocModel, Target};
use rustc_data_structures::fx::FxIndexSet;
use rustc_macros::HashStable_Generic;
@ -53,32 +53,28 @@ impl X86InlineAsmRegClass {
}
}
pub fn suggest_modifier(
self,
arch: InlineAsmArch,
ty: InlineAsmType,
) -> Option<(char, &'static str)> {
pub fn suggest_modifier(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<ModifierInfo> {
match self {
Self::reg => match ty.size().bits() {
16 => Some(('x', "ax")),
32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax")),
16 => Some(('x', "ax", 16).into()),
32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()),
_ => None,
},
Self::reg_abcd => match ty.size().bits() {
16 => Some(('x', "ax")),
32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax")),
16 => Some(('x', "ax", 16).into()),
32 if arch == InlineAsmArch::X86_64 => Some(('e', "eax", 32).into()),
_ => None,
},
Self::reg_byte => None,
Self::xmm_reg => None,
Self::ymm_reg => match ty.size().bits() {
256 => None,
_ => Some(('x', "xmm0")),
_ => Some(('x', "xmm0", 128).into()),
},
Self::zmm_reg => match ty.size().bits() {
512 => None,
256 => Some(('y', "ymm0")),
_ => Some(('x', "xmm0")),
256 => Some(('y', "ymm0", 256).into()),
_ => Some(('x', "xmm0", 128).into()),
},
Self::kreg | Self::kreg0 => None,
Self::mmx_reg | Self::x87_reg => None,
@ -86,19 +82,19 @@ impl X86InlineAsmRegClass {
}
}
pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)> {
pub fn default_modifier(self, arch: InlineAsmArch) -> Option<ModifierInfo> {
match self {
Self::reg | Self::reg_abcd => {
if arch == InlineAsmArch::X86_64 {
Some(('r', "rax"))
Some(('r', "rax", 64).into())
} else {
Some(('e', "eax"))
Some(('e', "eax", 32).into())
}
}
Self::reg_byte => None,
Self::xmm_reg => Some(('x', "xmm0")),
Self::ymm_reg => Some(('y', "ymm0")),
Self::zmm_reg => Some(('z', "zmm0")),
Self::xmm_reg => Some(('x', "xmm0", 128).into()),
Self::ymm_reg => Some(('y', "ymm0", 256).into()),
Self::zmm_reg => Some(('z', "zmm0", 512).into()),
Self::kreg | Self::kreg0 => None,
Self::mmx_reg | Self::x87_reg => None,
Self::tmm_reg => None,

View File

@ -55,7 +55,7 @@ impl IndexedVal for AllocId {
/// Utility function used to read an allocation data into a unassigned integer.
pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
let mut buf = [0u8; std::mem::size_of::<u128>()];
match MachineInfo::target_endianess() {
match MachineInfo::target_endianness() {
Endian::Little => {
bytes.read_exact(&mut buf[..bytes.len()])?;
Ok(u128::from_le_bytes(buf))
@ -70,7 +70,7 @@ pub(crate) fn read_target_uint(mut bytes: &[u8]) -> Result<u128, Error> {
/// Utility function used to read an allocation data into an assigned integer.
pub(crate) fn read_target_int(mut bytes: &[u8]) -> Result<i128, Error> {
let mut buf = [0u8; std::mem::size_of::<i128>()];
match MachineInfo::target_endianess() {
match MachineInfo::target_endianness() {
Endian::Little => {
bytes.read_exact(&mut buf[..bytes.len()])?;
Ok(i128::from_le_bytes(buf))

View File

@ -14,7 +14,7 @@ impl MachineInfo {
with(|cx| cx.target_info())
}
pub fn target_endianess() -> Endian {
pub fn target_endianness() -> Endian {
with(|cx| cx.target_info().endian)
}

View File

@ -470,7 +470,7 @@ extern "rust-intrinsic" {
/// No matter whether the output is an array or an unsigned integer, it is treated as a single
/// contiguous list of bits. The bitmask is always packed on the least-significant side of the
/// output, and padded with 0s in the most-significant bits. The order of the bits depends on
/// endianess:
/// endianness:
///
/// * On little endian, the least significant bit corresponds to the first vector element.
/// * On big endian, the least significant bit corresponds to the last vector element.

View File

@ -10,14 +10,16 @@
//! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
use r_efi::efi::{self, Guid};
use r_efi::protocols::{device_path, device_path_to_text};
use crate::ffi::OsString;
use crate::io::{self, const_io_error};
use crate::mem::{size_of, MaybeUninit};
use crate::os::uefi;
use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
use crate::ptr::NonNull;
use crate::{
io::{self, const_io_error},
os::uefi::env::boot_services,
};
use crate::slice;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys_common::wstr::WStrUnits;
const BOOT_SERVICES_UNAVAILABLE: io::Error =
const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
@ -142,9 +144,74 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
/// Get the Protocol for current system handle.
/// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
let system_handle = uefi::env::try_image_handle()?;
open_protocol(system_handle, protocol_guid).ok()
pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNull<T>> {
let system_handle = uefi::env::try_image_handle().ok_or(io::const_io_error!(
io::ErrorKind::NotFound,
"Protocol not found in Image handle"
))?;
open_protocol(system_handle, protocol_guid)
}
pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::Result<OsString> {
fn path_to_text(
protocol: NonNull<device_path_to_text::Protocol>,
path: NonNull<device_path::Protocol>,
) -> io::Result<OsString> {
let path_ptr: *mut r_efi::efi::Char16 = unsafe {
((*protocol.as_ptr()).convert_device_path_to_text)(
path.as_ptr(),
// DisplayOnly
r_efi::efi::Boolean::FALSE,
// AllowShortcuts
r_efi::efi::Boolean::FALSE,
)
};
// SAFETY: `convert_device_path_to_text` returns a pointer to a null-terminated UTF-16
// string, and that string cannot be deallocated prior to dropping the `WStrUnits`, so
// it's safe for `WStrUnits` to use.
let path_len = unsafe {
WStrUnits::new(path_ptr)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?
.count()
};
let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) });
if let Some(boot_services) = crate::os::uefi::env::boot_services() {
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
unsafe {
((*boot_services.as_ptr()).free_pool)(path_ptr.cast());
}
}
Ok(path)
}
static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
handle,
device_path_to_text::PROTOCOL_GUID,
) {
return path_to_text(protocol, path);
}
}
let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?;
for handle in device_path_to_text_handles {
if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
handle,
device_path_to_text::PROTOCOL_GUID,
) {
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
return path_to_text(protocol, path);
}
}
Err(io::const_io_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))
}
/// Get RuntimeServices

View File

@ -1,4 +1,4 @@
use super::{unsupported, RawOsError};
use super::{helpers, unsupported, RawOsError};
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::fmt;
@ -7,6 +7,7 @@ use crate::marker::PhantomData;
use crate::os::uefi;
use crate::path::{self, PathBuf};
use crate::ptr::NonNull;
use r_efi::efi::protocols::{device_path, loaded_image_device_path};
use r_efi::efi::Status;
pub fn errno() -> RawOsError {
@ -164,7 +165,10 @@ impl fmt::Display for JoinPathsError {
impl StdError for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
let protocol = helpers::image_handle_protocol::<device_path::Protocol>(
loaded_image_device_path::PROTOCOL_GUID,
)?;
helpers::device_path_to_text(protocol).map(PathBuf::from)
}
pub struct Env(!);

View File

@ -4,6 +4,7 @@
#![feature(staged_api)]
#![feature(c_unwind)]
#![feature(strict_provenance)]
#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
#![cfg_attr(
all(target_family = "wasm", not(target_os = "emscripten")),

View File

@ -59,7 +59,10 @@ pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwi
wasm_throw(0, exception.cast())
} else {
let _ = exception;
core::arch::wasm32::unreachable()
#[cfg(target_arch = "wasm32")]
core::arch::wasm32::unreachable();
#[cfg(target_arch = "wasm64")]
core::arch::wasm64::unreachable();
}
}
}

View File

@ -457,7 +457,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let bitmask_len = u32::try_from(bitmask_len).unwrap();
// To read the mask, we transmute it to an integer.
// That does the right thing wrt endianess.
// That does the right thing wrt endianness.
let mask_ty = this.machine.layouts.uint(mask.layout.size).unwrap();
let mask = mask.transmute(mask_ty, this)?;
let mask: u64 = this.read_scalar(&mask)?.to_bits(mask_ty.size)?.try_into().unwrap();
@ -509,7 +509,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
}
// We have to change the type of the place to be able to write `res` into it. This
// transmutes the integer to an array, which does the right thing wrt endianess.
// transmutes the integer to an array, which does the right thing wrt endianness.
let dest =
dest.transmute(this.machine.layouts.uint(dest.layout.size).unwrap(), this)?;
this.write_int(res, &dest)?;

View File

@ -38,7 +38,7 @@ impl FileDescriptor for Event {
}
/// A write call adds the 8-byte integer value supplied in
/// its buffer (in native endianess) to the counter. The maximum value that may be
/// its buffer (in native endianness) to the counter. The maximum value that may be
/// stored in the counter is the largest unsigned 64-bit value
/// minus 1 (i.e., 0xfffffffffffffffe). If the addition would
/// cause the counter's value to exceed the maximum, then the
@ -57,7 +57,7 @@ impl FileDescriptor for Event {
) -> InterpResult<'tcx, io::Result<usize>> {
let v1 = self.val.get();
let bytes: [u8; 8] = bytes.try_into().unwrap(); // FIXME fail gracefully when this has the wrong size
// Convert from target endianess to host endianess.
// Convert from target endianness to host endianness.
let num = match tcx.sess.target.endian {
Endian::Little => u64::from_le_bytes(bytes),
Endian::Big => u64::from_be_bytes(bytes),

View File

@ -34,6 +34,12 @@ pub struct Bar(i32);
#[repr(transparent)]
pub struct Type3<T>(T);
// repr(transparent) wrapper which engages in self-reference
#[repr(transparent)]
pub struct Type4(Type4Helper<Type4>);
#[repr(transparent)]
pub struct Type4Helper<T>(*mut T);
pub fn foo1(_: Type1) { }
// CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo2(_: Type1, _: Type1) { }
@ -52,6 +58,13 @@ pub fn foo8(_: Type3<Bar>, _: Type3<Bar>) { }
// CHECK: define{{.*}}4foo8{{.*}}!type ![[TYPE8:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo9(_: Type3<Bar>, _: Type3<Bar>, _: Type3<Bar>) { }
// CHECK: define{{.*}}4foo9{{.*}}!type ![[TYPE9:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo10(_: Type4) { }
// CHECK: define{{.*}}5foo10{{.*}}!type ![[TYPE10:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo11(_: Type4, _: Type4) { }
// CHECK: define{{.*}}5foo11{{.*}}!type ![[TYPE11:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
pub fn foo12(_: Type4, _: Type4, _: Type4) { }
// CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3FooE"}
// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3FooS_E"}
@ -62,3 +75,6 @@ pub fn foo9(_: Type3<Bar>, _: Type3<Bar>, _: Type3<Bar>) { }
// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3BarE"}
// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3BarS_E"}
// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}3BarS_S_E"}
// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvPu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type4E"}
// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvPu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type4S0_E"}
// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvPu{{[0-9]+}}NtC{{[[:print:]]+}}_{{[[:print:]]+}}5Type4S0_S0_E"}

View File

@ -4,8 +4,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0u8);
| ^^ --- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
= note: `#[warn(asm_sub_register)]` on by default
warning: formatting may not be suitable for sub-register argument
@ -14,8 +14,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0u16);
| ^^ ---- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:52:15
@ -23,8 +23,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0i32);
| ^^ ---- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:54:15
@ -32,8 +32,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0f32);
| ^^ ---- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:57:15
@ -41,8 +41,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(vreg) 0i16);
| ^^ ---- for this argument
|
= help: use `{0:h}` to have the register formatted as `h0`
= help: or use `{0:v}` to keep the default formatting of `v0`
= help: use `{0:h}` to have the register formatted as `h0` (for 16-bit values)
= help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:59:15
@ -50,8 +50,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(vreg) 0f32);
| ^^ ---- for this argument
|
= help: use `{0:s}` to have the register formatted as `s0`
= help: or use `{0:v}` to keep the default formatting of `v0`
= help: use `{0:s}` to have the register formatted as `s0` (for 32-bit values)
= help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:61:15
@ -59,8 +59,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(vreg) 0f64);
| ^^ ---- for this argument
|
= help: use `{0:d}` to have the register formatted as `d0`
= help: or use `{0:v}` to keep the default formatting of `v0`
= help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values)
= help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:63:15
@ -68,8 +68,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(vreg_low16) 0f64);
| ^^ ---- for this argument
|
= help: use `{0:d}` to have the register formatted as `d0`
= help: or use `{0:v}` to keep the default formatting of `v0`
= help: use `{0:d}` to have the register formatted as `d0` (for 64-bit values)
= help: or use `{0:v}` to keep the default formatting of `v0` (for 128-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:66:15
@ -77,8 +77,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{0} {0}", in(reg) 0i16);
| ^^^ ^^^ ---- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:68:15
@ -86,8 +86,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{0} {0:x}", in(reg) 0i16);
| ^^^ ---- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
error: type `i128` cannot be used with this register class
--> $DIR/type-check-3.rs:73:28

View File

@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
= help: use `{0:w}` to have the register formatted as `w0` (for 32-bit values)
= help: or use `{0:x}` to keep the default formatting of `x0` (for 64-bit values)
= note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted

View File

@ -194,8 +194,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
= help: use `{0:e}` to have the register formatted as `eax`
= help: or use `{0:r}` to keep the default formatting of `rax`
= help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values)
= help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values)
= note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted

View File

@ -44,8 +44,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{0} {0}", in(reg) 0i16);
| ^^^ ^^^ ---- for this argument
|
= help: use `{0:x}` to have the register formatted as `ax`
= help: or use `{0:r}` to keep the default formatting of `rax`
= help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values)
= help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values)
= note: `#[warn(asm_sub_register)]` on by default
warning: formatting may not be suitable for sub-register argument
@ -54,8 +54,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{0} {0:x}", in(reg) 0i16);
| ^^^ ---- for this argument
|
= help: use `{0:x}` to have the register formatted as `ax`
= help: or use `{0:r}` to keep the default formatting of `rax`
= help: use `{0:x}` to have the register formatted as `ax` (for 16-bit values)
= help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:38:15
@ -63,8 +63,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0i32);
| ^^ ---- for this argument
|
= help: use `{0:e}` to have the register formatted as `eax`
= help: or use `{0:r}` to keep the default formatting of `rax`
= help: use `{0:e}` to have the register formatted as `eax` (for 32-bit values)
= help: or use `{0:r}` to keep the default formatting of `rax` (for 64-bit values)
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:41:15
@ -72,8 +72,8 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(ymm_reg) 0i64);
| ^^ ---- for this argument
|
= help: use `{0:x}` to have the register formatted as `xmm0`
= help: or use `{0:y}` to keep the default formatting of `ymm0`
= help: use `{0:x}` to have the register formatted as `xmm0` (for 128-bit values)
= help: or use `{0:y}` to keep the default formatting of `ymm0` (for 256-bit values)
error: type `i8` cannot be used with this register class
--> $DIR/type-check-3.rs:52:28

View File

@ -0,0 +1,33 @@
// Check that encoding self-referential types works with #[repr(transparent)]
//@ needs-sanitizer-cfi
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
//@ only-linux
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
//@ run-pass
use std::marker::PhantomData;
struct X<T> {
_x: u8,
p: PhantomData<T>,
}
#[repr(transparent)]
struct Y(X<Y>);
trait Fooable {
fn foo(&self, y: Y);
}
struct Bar;
impl Fooable for Bar {
fn foo(&self, _: Y) {}
}
fn main() {
let x = &Bar as &dyn Fooable;
x.foo(Y(X {_x: 0, p: PhantomData}));
}

View File

@ -0,0 +1,22 @@
// Tests that calling a trait object method on a trait object with additional auto traits works.
//@ needs-sanitizer-cfi
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
//@ only-linux
//@ compile-flags: --crate-type=bin -Cprefer-dynamic=off -Clto -Zsanitizer=cfi
//@ compile-flags: -C target-feature=-crt-static -C codegen-units=1 -C opt-level=0
//@ run-pass
trait Foo {
fn foo(&self);
}
struct Bar;
impl Foo for Bar {
fn foo(&self) {}
}
pub fn main() {
let x: &(dyn Foo + Send) = &Bar;
x.foo();
}