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:
commit
4a52e9cc2a
@ -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, '*');
|
||||
|
@ -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.
|
||||
|
@ -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) };
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)",
|
||||
));
|
||||
},
|
||||
);
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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(!);
|
||||
|
@ -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")),
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)?;
|
||||
|
@ -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),
|
||||
|
@ -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"}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
33
tests/ui/sanitizer/cfi-self-ref.rs
Normal file
33
tests/ui/sanitizer/cfi-self-ref.rs
Normal 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}));
|
||||
}
|
22
tests/ui/sanitizer/cfi-virtual-auto.rs
Normal file
22
tests/ui/sanitizer/cfi-virtual-auto.rs
Normal 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();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user