Auto merge of #141984 - matthiaskrgr:rollup-wy6j9ca, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#137725 (Add `iter` macro)
 - rust-lang/rust#141455 (std: abort the process on failure to allocate a TLS key)
 - rust-lang/rust#141569 (Replace ad-hoc ABI "adjustments" with an `AbiMap` to `CanonAbi`)
 - rust-lang/rust#141698 (Use the informative error as the main const eval error message)
 - rust-lang/rust#141925 (Remove bootstrap cfgs from library/)
 - rust-lang/rust#141943 (Remove pre-expansion AST stats.)
 - rust-lang/rust#141945 (Remove `Path::is_ident`.)
 - rust-lang/rust#141957 (Add missing `dyn` keywords to tests that do not test for them Part 2)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-06-03 23:15:53 +00:00
569 changed files with 5958 additions and 5460 deletions
+136
View File
@@ -0,0 +1,136 @@
use std::fmt;
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic;
use crate::ExternAbi;
/// Calling convention to determine codegen
///
/// CanonAbi erases certain distinctions ExternAbi preserves, but remains target-dependent.
/// There are still both target-specific variants and aliasing variants, though much fewer.
/// The reason for this step is the frontend may wish to show an ExternAbi but implement that ABI
/// using a different ABI than the string per se, or describe irrelevant differences, e.g.
/// - extern "system"
/// - extern "cdecl"
/// - extern "C-unwind"
/// In that sense, this erases mere syntactic distinctions to create a canonical *directive*,
/// rather than picking the "actual" ABI.
#[derive(Copy, Clone, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum CanonAbi {
// NOTE: the use of nested variants for some ABIs is for many targets they don't matter,
// and this pushes the complexity of their reasoning to target-specific code,
// allowing a `match` to easily exhaustively ignore these subcategories of variants.
// Otherwise it is very tempting to avoid matching exhaustively!
C,
Rust,
RustCold,
/// ABIs relevant to 32-bit Arm targets
Arm(ArmCall),
/// ABI relevant to GPUs: the entry point for a GPU kernel
GpuKernel,
/// ABIs relevant to bare-metal interrupt targets
// FIXME(workingjubilee): a particular reason for this nesting is we might not need these?
// interrupt ABIs should have the same properties:
// - uncallable by Rust calls, as LLVM rejects it in most cases
// - uses a preserve-all-registers *callee* convention
// - should always return `-> !` (effectively... it can't use normal `ret`)
// what differs between targets is
// - allowed arguments: x86 differs slightly, having 2-3 arguments which are handled magically
// - may need special prologues/epilogues for some interrupts, without affecting "call ABI"
Interrupt(InterruptKind),
/// ABIs relevant to Windows or x86 targets
X86(X86Call),
}
impl fmt::Display for CanonAbi {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.to_erased_extern_abi().as_str().fmt(f)
}
}
impl CanonAbi {
/// convert to the ExternAbi that *shares a string* with this CanonAbi
///
/// A target-insensitive mapping of CanonAbi to ExternAbi, convenient for "forwarding" impls.
/// Importantly, the set of CanonAbi values is a logical *subset* of ExternAbi values,
/// so this is injective: if you take an ExternAbi to a CanonAbi and back, you have lost data.
const fn to_erased_extern_abi(self) -> ExternAbi {
match self {
CanonAbi::C => ExternAbi::C { unwind: false },
CanonAbi::Rust => ExternAbi::Rust,
CanonAbi::RustCold => ExternAbi::RustCold,
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },
ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,
ArmCall::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry,
},
CanonAbi::GpuKernel => ExternAbi::GpuKernel,
CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
InterruptKind::Avr => ExternAbi::AvrInterrupt,
InterruptKind::AvrNonBlocking => ExternAbi::AvrNonBlockingInterrupt,
InterruptKind::Msp430 => ExternAbi::Msp430Interrupt,
InterruptKind::RiscvMachine => ExternAbi::RiscvInterruptM,
InterruptKind::RiscvSupervisor => ExternAbi::RiscvInterruptS,
InterruptKind::X86 => ExternAbi::X86Interrupt,
},
CanonAbi::X86(x86_call) => match x86_call {
X86Call::Fastcall => ExternAbi::Fastcall { unwind: false },
X86Call::Stdcall => ExternAbi::Stdcall { unwind: false },
X86Call::SysV64 => ExternAbi::SysV64 { unwind: false },
X86Call::Thiscall => ExternAbi::Thiscall { unwind: false },
X86Call::Vectorcall => ExternAbi::Vectorcall { unwind: false },
X86Call::Win64 => ExternAbi::Win64 { unwind: false },
},
}
}
}
/// Callee codegen for interrupts
///
/// This is named differently from the "Call" enums because it is different:
/// these "ABI" differences are not relevant to callers, since there is "no caller".
/// These only affect callee codegen. making their categorization as distinct ABIs a bit peculiar.
#[derive(Copy, Clone, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum InterruptKind {
Avr,
AvrNonBlocking,
Msp430,
RiscvMachine,
RiscvSupervisor,
X86,
}
/// ABIs defined for x86-{32,64}
///
/// One of SysV64 or Win64 may alias the C ABI, and arguably Win64 is cross-platform now?
#[derive(Clone, Copy, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum X86Call {
/// "fastcall" has both GNU and Windows variants
Fastcall,
/// "stdcall" has both GNU and Windows variants
Stdcall,
SysV64,
Thiscall,
Vectorcall,
Win64,
}
/// ABIs defined for 32-bit Arm
#[derive(Copy, Clone, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum ArmCall {
Aapcs,
CCmseNonSecureCall,
CCmseNonSecureEntry,
}
+2 -5
View File
@@ -7,6 +7,8 @@
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable, Encodable};
use crate::AbiFromStrErr;
#[cfg(test)]
mod tests;
@@ -99,11 +101,6 @@ fn from_str(s: &str) -> Result<$e_name, Self::Err> {
}
}
#[derive(Debug)]
pub enum AbiFromStrErr {
Unknown,
}
abi_impls! {
ExternAbi = {
C { unwind: false } =><= "C",
+11 -2
View File
@@ -55,13 +55,14 @@
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_Generic};
mod callconv;
mod canon_abi;
mod extern_abi;
mod layout;
#[cfg(test)]
mod tests;
mod extern_abi;
pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
pub use extern_abi::{ExternAbi, all_names};
#[cfg(feature = "nightly")]
pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
@@ -1895,3 +1896,11 @@ pub enum StructKind {
/// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
Prefixed(Size, Align),
}
#[derive(Clone, Debug)]
pub enum AbiFromStrErr {
/// not a known ABI
Unknown,
/// no "-unwind" variant can be used here
NoExplicitUnwind,
}
+9 -13
View File
@@ -99,8 +99,15 @@ pub struct Path {
impl PartialEq<Symbol> for Path {
#[inline]
fn eq(&self, symbol: &Symbol) -> bool {
matches!(&self.segments[..], [segment] if segment.ident.name == *symbol)
fn eq(&self, name: &Symbol) -> bool {
if let [segment] = self.segments.as_ref()
&& segment.args.is_none()
&& segment.ident.name == *name
{
true
} else {
false
}
}
}
@@ -120,17 +127,6 @@ pub fn from_ident(ident: Ident) -> Path {
Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
}
pub fn is_ident(&self, name: Symbol) -> bool {
if let [segment] = self.segments.as_ref()
&& segment.args.is_none()
&& segment.ident.name == name
{
true
} else {
false
}
}
pub fn is_global(&self) -> bool {
self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot)
}
+8 -7
View File
@@ -1,4 +1,3 @@
use std::assert_matches::assert_matches;
use std::ops::ControlFlow;
use std::sync::Arc;
@@ -1199,11 +1198,13 @@ fn lower_expr_coroutine_closure(
let closure_def_id = self.local_def_id(closure_id);
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
assert_matches!(
coroutine_kind,
CoroutineKind::Async { .. },
"only async closures are supported currently"
);
let coroutine_desugaring = match coroutine_kind {
CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async,
CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen,
CoroutineKind::AsyncGen { span, .. } => {
span_bug!(span, "only async closures and `iter!` closures are supported currently")
}
};
let body = self.with_new_scopes(fn_decl_span, |this| {
let inner_decl =
@@ -1247,7 +1248,7 @@ fn lower_expr_coroutine_closure(
// Lower this as a `CoroutineClosure`. That will ensure that HIR typeck
// knows that a `FnDecl` output type like `-> &str` actually means
// "coroutine that returns &str", rather than directly returning a `&str`.
kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async),
kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring),
constness: hir::Constness::NotConst,
});
hir::ExprKind::Closure(c)
@@ -477,11 +477,12 @@ macro_rules! gate_all {
for span in spans {
if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines))
&& (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
&& (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
{
#[allow(rustc::untranslatable_diagnostic)]
// Don't know which of the two features to include in the
// error message, so I am arbitrarily picking one.
feature_err(&visitor.sess, sym::coroutines, *span, "yield syntax is experimental")
// Emit yield_expr as the error, since that will be sufficient. You can think of it
// as coroutines and gen_blocks imply yield_expr.
feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental")
.emit();
}
}
@@ -52,7 +52,7 @@ pub(super) fn check_signature_annotation(&mut self) {
assert_matches!(
self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
Some(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::Gen,
hir::CoroutineSource::Closure
)),
"this needs to be modified if we're lowering non-async closures"
+53
View File
@@ -0,0 +1,53 @@
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token};
use rustc_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_span::Span;
pub(crate) fn expand<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
let closure = match parse_closure(cx, sp, tts) {
Ok(parsed) => parsed,
Err(err) => {
return ExpandResult::Ready(DummyResult::any(sp, err.emit()));
}
};
ExpandResult::Ready(base::MacEager::expr(closure))
}
fn parse_closure<'a>(
cx: &mut ExtCtxt<'a>,
span: Span,
stream: TokenStream,
) -> PResult<'a, P<Expr>> {
let mut closure_parser = cx.new_parser_from_tts(stream);
let coroutine_kind = Some(CoroutineKind::Gen {
span,
closure_id: DUMMY_NODE_ID,
return_impl_trait_id: DUMMY_NODE_ID,
});
let mut closure = closure_parser.parse_expr()?;
match &mut closure.kind {
ast::ExprKind::Closure(c) => {
if let Some(kind) = c.coroutine_kind {
cx.dcx().span_err(kind.span(), "only plain closures allowed in `iter!`");
}
c.coroutine_kind = coroutine_kind;
if closure_parser.token != token::Eof {
closure_parser.unexpected()?;
}
Ok(closure)
}
_ => {
cx.dcx().span_err(closure.span, "`iter!` body must be a closure");
Err(closure_parser.unexpected().unwrap_err())
}
}
}
+2
View File
@@ -47,6 +47,7 @@
mod format;
mod format_foreign;
mod global_allocator;
mod iter;
mod log_syntax;
mod pattern_type;
mod source_util;
@@ -95,6 +96,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
include: source_util::expand_include,
include_bytes: source_util::expand_include_bytes,
include_str: source_util::expand_include_str,
iter: iter::expand,
line: source_util::expand_line,
log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod,
+20 -25
View File
@@ -10,7 +10,7 @@
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
use cranelift_codegen::isa::CallConv;
use cranelift_module::ModuleError;
use rustc_abi::ExternAbi;
use rustc_abi::{CanonAbi, ExternAbi, X86Call};
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -19,7 +19,7 @@
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::Session;
use rustc_span::source_map::Spanned;
use rustc_target::callconv::{Conv, FnAbi, PassMode};
use rustc_target::callconv::{FnAbi, PassMode};
use smallvec::SmallVec;
use self::pass_mode::*;
@@ -42,32 +42,27 @@ fn clif_sig_from_fn_abi<'tcx>(
Signature { params, returns, call_conv }
}
pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv {
pub(crate) fn conv_to_call_conv(
sess: &Session,
c: CanonAbi,
default_call_conv: CallConv,
) -> CallConv {
match c {
Conv::Rust | Conv::C => default_call_conv,
Conv::Cold | Conv::PreserveMost | Conv::PreserveAll => CallConv::Cold,
Conv::X86_64SysV => CallConv::SystemV,
Conv::X86_64Win64 => CallConv::WindowsFastcall,
CanonAbi::Rust | CanonAbi::C => default_call_conv,
CanonAbi::RustCold => CallConv::Cold,
// Should already get a back compat warning
Conv::X86Fastcall | Conv::X86Stdcall | Conv::X86ThisCall | Conv::X86VectorCall => {
default_call_conv
}
CanonAbi::X86(x86_call) => match x86_call {
X86Call::SysV64 => CallConv::SystemV,
X86Call::Win64 => CallConv::WindowsFastcall,
// Should already get a back compat warning
_ => default_call_conv,
},
Conv::X86Intr | Conv::RiscvInterrupt { .. } => {
sess.dcx().fatal(format!("interrupt call conv {c:?} not yet implemented"))
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) => {
sess.dcx().fatal("call conv {c:?} is not yet implemented")
}
Conv::ArmAapcs => sess.dcx().fatal("aapcs call conv not yet implemented"),
Conv::CCmseNonSecureCall => {
sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented");
}
Conv::CCmseNonSecureEntry => {
sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented");
}
Conv::Msp430Intr | Conv::GpuKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
CanonAbi::GpuKernel => {
unreachable!("tried to use {c:?} call conv which only exists on an unsupported target")
}
}
}
@@ -610,7 +605,7 @@ fn adjust_call_for_c_variadic<'tcx>(
target: CallTarget,
call_args: &mut Vec<Value>,
) {
if fn_abi.conv != Conv::C {
if fn_abi.conv != CanonAbi::C {
fx.tcx.dcx().span_fatal(
source_info.span,
format!("Variadic call for non-C abi {:?}", fn_abi.conv),
+28 -45
View File
@@ -1,7 +1,7 @@
#[cfg(feature = "master")]
use gccjit::FnAttribute;
use gccjit::{ToLValue, ToRValue, Type};
use rustc_abi::{Reg, RegKind};
use rustc_abi::{ArmCall, CanonAbi, InterruptKind, Reg, RegKind, X86Call};
use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
@@ -10,8 +10,6 @@
#[cfg(feature = "master")]
use rustc_session::config;
use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode};
#[cfg(feature = "master")]
use rustc_target::callconv::{Conv, RiscvInterruptKind};
use crate::builder::Builder;
use crate::context::CodegenCx;
@@ -238,29 +236,16 @@ fn gcc_cconv(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Option<FnAttribute<'gcc>> {
}
#[cfg(feature = "master")]
pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> {
pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &str) -> Option<FnAttribute<'gcc>> {
let attribute = match conv {
Conv::C | Conv::Rust => return None,
Conv::CCmseNonSecureCall => {
if arch == "arm" {
FnAttribute::ArmCmseNonsecureCall
} else {
return None;
}
}
Conv::CCmseNonSecureEntry => {
if arch == "arm" {
FnAttribute::ArmCmseNonsecureEntry
} else {
return None;
}
}
Conv::Cold => FnAttribute::Cold,
// NOTE: the preserve attributes are not yet implemented in GCC:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110899
Conv::PreserveMost => return None,
Conv::PreserveAll => return None,
Conv::GpuKernel => {
CanonAbi::C | CanonAbi::Rust => return None,
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall,
ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry,
ArmCall::Aapcs => FnAttribute::ArmPcs("aapcs"),
},
CanonAbi::RustCold => FnAttribute::Cold,
CanonAbi::GpuKernel => {
if arch == "amdgpu" {
FnAttribute::GcnAmdGpuHsaKernel
} else if arch == "nvptx64" {
@@ -270,26 +255,24 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<
}
}
// TODO(antoyo): check if those AVR attributes are mapped correctly.
Conv::AvrInterrupt => FnAttribute::AvrSignal,
Conv::AvrNonBlockingInterrupt => FnAttribute::AvrInterrupt,
Conv::ArmAapcs => FnAttribute::ArmPcs("aapcs"),
Conv::Msp430Intr => FnAttribute::Msp430Interrupt,
Conv::RiscvInterrupt { kind } => {
let kind = match kind {
RiscvInterruptKind::Machine => "machine",
RiscvInterruptKind::Supervisor => "supervisor",
};
FnAttribute::RiscvInterrupt(kind)
}
Conv::X86Fastcall => FnAttribute::X86FastCall,
Conv::X86Intr => FnAttribute::X86Interrupt,
Conv::X86Stdcall => FnAttribute::X86Stdcall,
Conv::X86ThisCall => FnAttribute::X86ThisCall,
// NOTE: the vectorcall calling convention is not yet implemented in GCC:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
Conv::X86VectorCall => return None,
Conv::X86_64SysV => FnAttribute::X86SysvAbi,
Conv::X86_64Win64 => FnAttribute::X86MsAbi,
CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
InterruptKind::Avr => FnAttribute::AvrSignal,
InterruptKind::AvrNonBlocking => FnAttribute::AvrInterrupt,
InterruptKind::Msp430 => FnAttribute::Msp430Interrupt,
InterruptKind::RiscvMachine => FnAttribute::RiscvInterrupt("machine"),
InterruptKind::RiscvSupervisor => FnAttribute::RiscvInterrupt("supervisor"),
InterruptKind::X86 => FnAttribute::X86Interrupt,
},
CanonAbi::X86(x86_call) => match x86_call {
X86Call::Fastcall => FnAttribute::X86FastCall,
X86Call::Stdcall => FnAttribute::X86Stdcall,
X86Call::Thiscall => FnAttribute::X86ThisCall,
// // NOTE: the vectorcall calling convention is not yet implemented in GCC:
// // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485
X86Call::Vectorcall => return None,
X86Call::SysV64 => FnAttribute::X86SysvAbi,
X86Call::Win64 => FnAttribute::X86MsAbi,
},
};
Some(attribute)
}
+3 -3
View File
@@ -3,11 +3,11 @@
//! 128-bit integers on 32-bit platforms and thus require to be handled manually.
use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
use rustc_abi::{Endian, ExternAbi};
use rustc_abi::{CanonAbi, Endian, ExternAbi};
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
use rustc_middle::ty::{self, Ty};
use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
use rustc_target::callconv::{ArgAbi, ArgAttributes, FnAbi, PassMode};
use crate::builder::{Builder, ToGccComp};
use crate::common::{SignType, TypeReflection};
@@ -397,7 +397,7 @@ pub fn operation_with_overflow(
ret: arg_abi,
c_variadic: false,
fixed_count: 3,
conv: Conv::C,
conv: CanonAbi::C,
can_unwind: false,
};
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false });
+40 -29
View File
@@ -2,7 +2,10 @@
use std::cmp;
use libc::c_uint;
use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size};
use rustc_abi::{
ArmCall, BackendRepr, CanonAbi, HasDataLayout, InterruptKind, Primitive, Reg, RegKind, Size,
X86Call,
};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
@@ -12,7 +15,7 @@
use rustc_middle::{bug, ty};
use rustc_session::config;
use rustc_target::callconv::{
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode,
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode,
};
use rustc_target::spec::SanitizerSet;
use smallvec::SmallVec;
@@ -409,11 +412,17 @@ fn apply_attrs_llfn(
if !self.can_unwind {
func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(cx.llcx));
}
if let Conv::RiscvInterrupt { kind } = self.conv {
func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
}
if let Conv::CCmseNonSecureEntry = self.conv {
func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
match self.conv {
CanonAbi::Interrupt(InterruptKind::RiscvMachine) => {
func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "machine"))
}
CanonAbi::Interrupt(InterruptKind::RiscvSupervisor) => {
func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "supervisor"))
}
CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) => {
func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
}
_ => (),
}
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
@@ -600,7 +609,7 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll V
llvm::SetInstructionCallConv(callsite, cconv);
}
if self.conv == Conv::CCmseNonSecureCall {
if self.conv == CanonAbi::Arm(ArmCall::CCmseNonSecureCall) {
// This will probably get ignored on all targets but those supporting the TrustZone-M
// extension (thumbv8m targets).
let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call");
@@ -636,17 +645,11 @@ fn get_param(&mut self, index: usize) -> Self::Value {
}
impl llvm::CallConv {
pub(crate) fn from_conv(conv: Conv, arch: &str) -> Self {
pub(crate) fn from_conv(conv: CanonAbi, arch: &str) -> Self {
match conv {
Conv::C
| Conv::Rust
| Conv::CCmseNonSecureCall
| Conv::CCmseNonSecureEntry
| Conv::RiscvInterrupt { .. } => llvm::CCallConv,
Conv::Cold => llvm::ColdCallConv,
Conv::PreserveMost => llvm::PreserveMost,
Conv::PreserveAll => llvm::PreserveAll,
Conv::GpuKernel => {
CanonAbi::C | CanonAbi::Rust => llvm::CCallConv,
CanonAbi::RustCold => llvm::PreserveMost,
CanonAbi::GpuKernel => {
if arch == "amdgpu" {
llvm::AmdgpuKernel
} else if arch == "nvptx64" {
@@ -655,17 +658,25 @@ pub(crate) fn from_conv(conv: Conv, arch: &str) -> Self {
panic!("Architecture {arch} does not support GpuKernel calling convention");
}
}
Conv::AvrInterrupt => llvm::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
Conv::ArmAapcs => llvm::ArmAapcsCallConv,
Conv::Msp430Intr => llvm::Msp430Intr,
Conv::X86Fastcall => llvm::X86FastcallCallConv,
Conv::X86Intr => llvm::X86_Intr,
Conv::X86Stdcall => llvm::X86StdcallCallConv,
Conv::X86ThisCall => llvm::X86_ThisCall,
Conv::X86VectorCall => llvm::X86_VectorCall,
Conv::X86_64SysV => llvm::X86_64_SysV,
Conv::X86_64Win64 => llvm::X86_64_Win64,
CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
InterruptKind::Avr => llvm::AvrInterrupt,
InterruptKind::AvrNonBlocking => llvm::AvrNonBlockingInterrupt,
InterruptKind::Msp430 => llvm::Msp430Intr,
InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => llvm::CCallConv,
InterruptKind::X86 => llvm::X86_Intr,
},
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::Aapcs => llvm::ArmAapcsCallConv,
ArmCall::CCmseNonSecureCall | ArmCall::CCmseNonSecureEntry => llvm::CCallConv,
},
CanonAbi::X86(x86_call) => match x86_call {
X86Call::Fastcall => llvm::X86FastcallCallConv,
X86Call::Stdcall => llvm::X86StdcallCallConv,
X86Call::SysV64 => llvm::X86_64_SysV,
X86Call::Thiscall => llvm::X86_ThisCall,
X86Call::Vectorcall => llvm::X86_VectorCall,
X86Call::Win64 => llvm::X86_64_Win64,
},
}
}
}
@@ -1,5 +1,6 @@
use std::collections::hash_map::Entry::*;
use rustc_abi::{CanonAbi, X86Call};
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::def::DefKind;
@@ -14,7 +15,6 @@
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::callconv::Conv;
use rustc_target::spec::{SanitizerSet, TlsModel};
use tracing::debug;
@@ -652,7 +652,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
fn calling_convention_for_symbol<'tcx>(
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,
) -> (Conv, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) {
) -> (CanonAbi, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) {
let instance = match symbol {
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
if tcx.is_static(def_id) =>
@@ -683,7 +683,7 @@ fn calling_convention_for_symbol<'tcx>(
})
.map(|fnabi| (fnabi.conv, &fnabi.args[..]))
// FIXME(workingjubilee): why don't we know the convention here?
.unwrap_or((Conv::Rust, &[]))
.unwrap_or((CanonAbi::Rust, &[]))
}
/// This is the symbol name of the given instance as seen by the linker.
@@ -717,14 +717,14 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
_ => return undecorated,
};
let (conv, args) = calling_convention_for_symbol(tcx, symbol);
let (callconv, args) = calling_convention_for_symbol(tcx, symbol);
// Decorate symbols with prefixes, suffixes and total number of bytes of arguments.
// Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170
let (prefix, suffix) = match conv {
Conv::X86Fastcall => ("@", "@"),
Conv::X86Stdcall => ("_", "@"),
Conv::X86VectorCall => ("", "@@"),
let (prefix, suffix) = match callconv {
CanonAbi::X86(X86Call::Fastcall) => ("@", "@"),
CanonAbi::X86(X86Call::Stdcall) => ("_", "@"),
CanonAbi::X86(X86Call::Vectorcall) => ("", "@@"),
_ => {
if let Some(prefix) = prefix {
undecorated.insert(0, prefix);
@@ -758,9 +758,9 @@ pub(crate) fn extend_exported_symbols<'tcx>(
symbol: ExportedSymbol<'tcx>,
instantiating_crate: CrateNum,
) {
let (conv, _) = calling_convention_for_symbol(tcx, symbol);
let (callconv, _) = calling_convention_for_symbol(tcx, symbol);
if conv != Conv::GpuKernel || tcx.sess.target.os != "amdhsa" {
if callconv != CanonAbi::GpuKernel || tcx.sess.target.os != "amdhsa" {
return;
}
+4 -4
View File
@@ -89,9 +89,9 @@ const_eval_dyn_call_not_a_method =
`dyn` call trying to call something that is not a method
const_eval_error = {$error_kind ->
[static] could not evaluate static initializer
[const] evaluation of constant value failed
[const_with_path] evaluation of `{$instance}` failed
[static] evaluation of static initializer failed here
[const] evaluation of constant value failed here
[const_with_path] evaluation of `{$instance}` failed here
*[other] {""}
}
@@ -118,7 +118,7 @@ const_eval_frame_note_inner = inside {$where_ ->
const_eval_frame_note_last = the failure occurred here
const_eval_incompatible_calling_conventions =
calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
calling a function with calling convention "{$callee_conv}" using calling convention "{$caller_conv}"
const_eval_incompatible_return_types =
calling a function with return type {$callee_ty} passing return place of type {$caller_ty}
@@ -589,12 +589,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref()
&& let Some(
coroutine_kind @ hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
_,
),
) = self.tcx.coroutine_kind(def_id)
&& let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
{
self.check_op(ops::Coroutine(coroutine_kind));
}
@@ -486,24 +486,25 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
pub(crate) struct Coroutine(pub hir::CoroutineKind);
impl<'tcx> NonConstOp<'tcx> for Coroutine {
fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status {
if let hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Block,
) = self.0
{
Status::Unstable {
match self.0 {
hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Block,
)
// FIXME(coroutines): eventually we want to gate const coroutine coroutines behind a
// different feature.
| hir::CoroutineKind::Coroutine(_) => Status::Unstable {
gate: sym::const_async_blocks,
gate_already_checked: false,
safe_to_expose_on_stable: false,
is_function_call: false,
}
} else {
Status::Forbidden
},
_ => Status::Forbidden,
}
}
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind());
let msg = format!("{} are not allowed in {}s", self.0.to_plural_string(), ccx.const_kind());
if let Status::Unstable { gate, .. } = self.status_in_item(ccx) {
ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate)
} else {
@@ -1,6 +1,6 @@
use std::mem;
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
@@ -131,10 +131,10 @@ pub fn get_span_and_frames<'tcx>(
/// Create a diagnostic for a const eval error.
///
/// This will use the `mk` function for creating the error which will get passed labels according to
/// the `InterpError` and the span and a stacktrace of current execution according to
/// `get_span_and_frames`.
pub(super) fn report<'tcx, C, F, E>(
/// This will use the `mk` function for adding more information to the error.
/// You can use it to add a stacktrace of current execution according to
/// `get_span_and_frames` or just give context on where the const eval error happened.
pub(super) fn report<'tcx, C, F>(
tcx: TyCtxt<'tcx>,
error: InterpErrorKind<'tcx>,
span: Span,
@@ -143,8 +143,7 @@ pub(super) fn report<'tcx, C, F, E>(
) -> ErrorHandled
where
C: FnOnce() -> (Span, Vec<FrameNote>),
F: FnOnce(Span, Vec<FrameNote>) -> E,
E: Diagnostic<'tcx>,
F: FnOnce(&mut Diag<'_>, Span, Vec<FrameNote>),
{
// Special handling for certain errors
match error {
@@ -163,8 +162,7 @@ pub(super) fn report<'tcx, C, F, E>(
_ => {
let (our_span, frames) = get_span_and_frames();
let span = span.substitute_dummy(our_span);
let err = mk(span, frames);
let mut err = tcx.dcx().create_err(err);
let mut err = tcx.dcx().struct_span_err(our_span, error.diagnostic_message());
// We allow invalid programs in infallible promoteds since invalid layouts can occur
// anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
let allowed_in_infallible = matches!(
@@ -172,11 +170,9 @@ pub(super) fn report<'tcx, C, F, E>(
InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
);
let msg = error.diagnostic_message();
error.add_args(&mut err);
// Use *our* span to label the interp error
err.span_label(our_span, msg);
mk(&mut err, span, frames);
let g = err.emit();
let reported = if allowed_in_infallible {
ReportedErrorInfo::allowed_in_infallible(g)
@@ -2,6 +2,7 @@
use either::{Left, Right};
use rustc_abi::{self as abi, BackendRepr};
use rustc_errors::E0080;
use rustc_hir::def::DefKind;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo};
use rustc_middle::mir::{self, ConstAlloc, ConstValue};
@@ -290,12 +291,18 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|error| {
let span = tcx.def_span(def_id);
// FIXME(oli-obk): why don't we have any tests for this code path?
super::report(
tcx,
error.into_kind(),
span,
|| (span, vec![]),
|span, _| errors::NullaryIntrinsicError { span },
|diag, span, _| {
diag.span_label(
span,
crate::fluent_generated::const_eval_nullary_intrinsic_fail,
);
},
)
},
);
@@ -443,11 +450,15 @@ fn report_eval_error<'tcx>(
error,
DUMMY_SP,
|| super::get_span_and_frames(ecx.tcx, ecx.stack()),
|span, frames| errors::ConstEvalError {
span,
error_kind: kind,
instance,
frame_notes: frames,
|diag, span, frames| {
// FIXME(oli-obk): figure out how to use structured diagnostics again.
diag.code(E0080);
diag.span_label(span, crate::fluent_generated::const_eval_error);
diag.arg("instance", instance);
diag.arg("error_kind", kind);
for frame in frames {
diag.subdiagnostic(frame);
}
},
)
}
@@ -477,6 +488,15 @@ fn report_validation_error<'tcx>(
error,
DUMMY_SP,
|| crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes },
move |diag, span, frames| {
// FIXME(oli-obk): figure out how to use structured diagnostics again.
diag.code(E0080);
diag.span_label(span, crate::fluent_generated::const_eval_validation_failure);
diag.note(crate::fluent_generated::const_eval_validation_failure_note);
for frame in frames {
diag.subdiagnostic(frame);
}
diag.subdiagnostic(raw_bytes);
},
)
}
-32
View File
@@ -439,38 +439,6 @@ pub struct LiveDrop<'tcx> {
pub dropped_at: Span,
}
#[derive(Diagnostic)]
#[diag(const_eval_error, code = E0080)]
pub struct ConstEvalError {
#[primary_span]
pub span: Span,
/// One of "const", "const_with_path", and "static"
pub error_kind: &'static str,
pub instance: String,
#[subdiagnostic]
pub frame_notes: Vec<FrameNote>,
}
#[derive(Diagnostic)]
#[diag(const_eval_nullary_intrinsic_fail)]
pub struct NullaryIntrinsicError {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(const_eval_validation_failure, code = E0080)]
pub struct ValidationFailure {
#[primary_span]
pub span: Span,
#[note(const_eval_validation_failure_note)]
pub ub_note: (),
#[subdiagnostic]
pub frames: Vec<FrameNote>,
#[subdiagnostic]
pub raw_bytes: RawBytesNote,
}
pub trait ReportErrorExt {
/// Returns the diagnostic message for this error.
fn diagnostic_message(&self) -> DiagMessage;
+9 -2
View File
@@ -2061,12 +2061,19 @@ pub fn movability(self) -> Movability {
CoroutineKind::Coroutine(mov) => mov,
}
}
}
impl CoroutineKind {
pub fn is_fn_like(self) -> bool {
matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn))
}
pub fn to_plural_string(&self) -> String {
match self {
CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"),
CoroutineKind::Desugared(d, CoroutineSource::Block) => format!("{d:#}blocks"),
CoroutineKind::Desugared(d, CoroutineSource::Closure) => format!("{d:#}closure bodies"),
CoroutineKind::Coroutine(_) => "coroutines".to_string(),
}
}
}
impl fmt::Display for CoroutineKind {
+15 -5
View File
@@ -204,14 +204,19 @@ pub(crate) fn check_expr_closure(
)
}
hir::ClosureKind::CoroutineClosure(kind) => {
// async closures always return the type ascribed after the `->` (if present),
// and yield `()`.
let (bound_return_ty, bound_yield_ty) = match kind {
hir::CoroutineDesugaring::Gen => {
// `iter!` closures always return unit and yield the `Iterator::Item` type
// that we have to infer.
(tcx.types.unit, self.infcx.next_ty_var(expr_span))
}
hir::CoroutineDesugaring::Async => {
// async closures always return the type ascribed after the `->` (if present),
// and yield `()`.
(bound_sig.skip_binder().output(), tcx.types.unit)
}
hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen => {
todo!("`gen` and `async gen` closures not supported yet")
hir::CoroutineDesugaring::AsyncGen => {
todo!("`async gen` closures not supported yet")
}
};
// Compute all of the variables that will be used to populate the coroutine.
@@ -465,7 +470,12 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
if let Some(trait_def_id) = trait_def_id {
let found_kind = match closure_kind {
hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id),
hir::ClosureKind::Closure
// FIXME(iter_macro): Someday we'll probably want iterator closures instead of
// just using Fn* for iterators.
| hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {
self.tcx.fn_trait_kind_from_def_id(trait_def_id)
}
hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => self
.tcx
.async_fn_trait_kind_from_def_id(trait_def_id)
+1 -5
View File
@@ -60,10 +60,6 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
guar.raise_fatal();
});
if sess.opts.unstable_opts.input_stats {
input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
}
rustc_builtin_macros::cmdline_attrs::inject(
&mut krate,
&sess.psess,
@@ -298,7 +294,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
let mut lint_buffer = resolver.lint_buffer.steal();
if sess.opts.unstable_opts.input_stats {
input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats");
}
// Needs to go *after* expansion to be able to check the results of macro expansion.
@@ -1,6 +1,6 @@
//! This module ensures that if a function's ABI requires a particular target feature,
//! that target feature is enabled both on the callee and all callers.
use rustc_abi::{BackendRepr, RegKind};
use rustc_abi::{BackendRepr, CanonAbi, RegKind, X86Call};
use rustc_hir::{CRATE_HIR_ID, HirId};
use rustc_middle::mir::{self, Location, traversal};
use rustc_middle::ty::layout::LayoutCx;
@@ -8,7 +8,7 @@
use rustc_session::lint::builtin::WASM_C_ABI;
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
use crate::errors;
@@ -72,7 +72,7 @@ fn do_check_simd_vector_abi<'tcx>(
}
}
// The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) {
if abi.conv == CanonAbi::X86(X86Call::Vectorcall) && !have_feature(sym::sse2) {
let (span, _hir_id) = loc();
tcx.dcx().emit_err(errors::AbiRequiredTargetFeature {
span,
@@ -128,7 +128,7 @@ fn do_check_wasm_abi<'tcx>(
if !(tcx.sess.target.arch == "wasm32"
&& tcx.sess.target.os == "unknown"
&& tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
&& abi.conv == Conv::C)
&& abi.conv == CanonAbi::C)
{
return;
}
+1 -1
View File
@@ -834,7 +834,7 @@ fn parse_expr_borrow(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
// guides recovery in case we write `&raw expr`.
if borrow_kind == ast::BorrowKind::Ref
&& mutbl == ast::Mutability::Not
&& matches!(&expr.kind, ExprKind::Path(None, p) if p.is_ident(kw::Raw))
&& matches!(&expr.kind, ExprKind::Path(None, p) if *p == kw::Raw)
{
self.expected_token_types.insert(TokenType::KwMut);
self.expected_token_types.insert(TokenType::KwConst);
+1 -1
View File
@@ -713,7 +713,7 @@ pub(super) fn parse_block_common(
/// Parses the rest of a block expression or function body.
/// Precondition: already parsed the '{'.
pub(crate) fn parse_block_tail(
pub fn parse_block_tail(
&mut self,
lo: Span,
s: BlockCheckMode,
@@ -4,10 +4,11 @@
//! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler,
//! see design document in the tracking issue #89653.
use rustc_abi::CanonAbi;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::bug;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_target::callconv::{Conv, FnAbi, PassMode};
use rustc_target::callconv::{FnAbi, PassMode};
use tracing::instrument;
mod encode;
@@ -45,7 +46,7 @@ pub fn typeid_for_fnabi<'tcx>(
let mut encode_ty_options = EncodeTyOptions::from_bits(options.bits())
.unwrap_or_else(|| bug!("typeid_for_fnabi: invalid option(s) `{:?}`", options.bits()));
match fn_abi.conv {
Conv::C => {
CanonAbi::C => {
encode_ty_options.insert(EncodeTyOptions::GENERALIZE_REPR_C);
}
_ => {
@@ -2,8 +2,9 @@
#![allow(rustc::usage_of_qualified_ty)]
use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
use rustc_middle::ty;
use rustc_target::callconv::{self, Conv};
use rustc_target::callconv;
use stable_mir::abi::{
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, Layout,
LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape,
@@ -69,7 +70,7 @@ impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
assert!(self.args.len() >= self.fixed_count as usize);
assert!(!self.c_variadic || matches!(self.conv, Conv::C));
assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C));
FnAbi {
args: self.args.as_ref().stable(tables),
ret: self.ret.stable(tables),
@@ -92,31 +93,37 @@ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
}
}
impl<'tcx> Stable<'tcx> for callconv::Conv {
impl<'tcx> Stable<'tcx> for CanonAbi {
type T = CallConvention;
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
match self {
Conv::C => CallConvention::C,
Conv::Rust => CallConvention::Rust,
Conv::Cold => CallConvention::Cold,
Conv::PreserveMost => CallConvention::PreserveMost,
Conv::PreserveAll => CallConvention::PreserveAll,
Conv::ArmAapcs => CallConvention::ArmAapcs,
Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
Conv::Msp430Intr => CallConvention::Msp430Intr,
Conv::X86Fastcall => CallConvention::X86Fastcall,
Conv::X86Intr => CallConvention::X86Intr,
Conv::X86Stdcall => CallConvention::X86Stdcall,
Conv::X86ThisCall => CallConvention::X86ThisCall,
Conv::X86VectorCall => CallConvention::X86VectorCall,
Conv::X86_64SysV => CallConvention::X86_64SysV,
Conv::X86_64Win64 => CallConvention::X86_64Win64,
Conv::GpuKernel => CallConvention::GpuKernel,
Conv::AvrInterrupt => CallConvention::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => CallConvention::AvrNonBlockingInterrupt,
Conv::RiscvInterrupt { .. } => CallConvention::RiscvInterrupt,
CanonAbi::C => CallConvention::C,
CanonAbi::Rust => CallConvention::Rust,
CanonAbi::RustCold => CallConvention::Cold,
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::Aapcs => CallConvention::ArmAapcs,
ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
},
CanonAbi::GpuKernel => CallConvention::GpuKernel,
CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
InterruptKind::Avr => CallConvention::AvrInterrupt,
InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt,
InterruptKind::Msp430 => CallConvention::Msp430Intr,
InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => {
CallConvention::RiscvInterrupt
}
InterruptKind::X86 => CallConvention::X86Intr,
},
CanonAbi::X86(x86_call) => match x86_call {
X86Call::Fastcall => CallConvention::X86Fastcall,
X86Call::Stdcall => CallConvention::X86Stdcall,
X86Call::SysV64 => CallConvention::X86_64SysV,
X86Call::Thiscall => CallConvention::X86ThisCall,
X86Call::Vectorcall => CallConvention::X86VectorCall,
X86Call::Win64 => CallConvention::X86_64Win64,
},
}
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
use rustc_abi::{HasDataLayout, TyAbiInterface};
use rustc_abi::{ArmCall, CanonAbi, HasDataLayout, TyAbiInterface};
use crate::callconv::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
use crate::spec::HasTargetSpec;
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
@@ -90,7 +90,7 @@ pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
// If this is a target with a hard-float ABI, and the function is not explicitly
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
let vfp = cx.target_spec().llvm_target.ends_with("hf")
&& fn_abi.conv != Conv::ArmAapcs
&& fn_abi.conv != CanonAbi::Arm(ArmCall::Aapcs)
&& !fn_abi.c_variadic;
if !fn_abi.ret.is_ignore() {
+4 -105
View File
@@ -1,13 +1,12 @@
use std::fmt::Display;
use std::str::FromStr;
use std::{fmt, iter};
use rustc_abi::{
AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, Scalar,
Size, TyAbiInterface, TyAndLayout,
AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, HasDataLayout, Primitive, Reg, RegKind,
Scalar, Size, TyAbiInterface, TyAndLayout,
};
use rustc_macros::HashStable_Generic;
pub use crate::spec::AbiMap;
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi};
mod aarch64;
@@ -529,41 +528,6 @@ pub fn eq_abi(&self, other: &Self) -> bool
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum Conv {
// General language calling conventions, for which every target
// should have its own backend (e.g. LLVM) support.
C,
Rust,
Cold,
PreserveMost,
PreserveAll,
// Target-specific calling conventions.
ArmAapcs,
CCmseNonSecureCall,
CCmseNonSecureEntry,
Msp430Intr,
GpuKernel,
X86Fastcall,
X86Intr,
X86Stdcall,
X86ThisCall,
X86VectorCall,
X86_64SysV,
X86_64Win64,
AvrInterrupt,
AvrNonBlockingInterrupt,
RiscvInterrupt { kind: RiscvInterruptKind },
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum RiscvInterruptKind {
Machine,
@@ -605,7 +569,7 @@ pub struct FnAbi<'a, Ty> {
/// This can be used to know whether an argument is variadic or not.
pub fixed_count: u32,
/// The calling convention of this function.
pub conv: Conv,
pub conv: CanonAbi,
/// Indicates if an unwind may happen across a call to this function.
pub can_unwind: bool,
}
@@ -696,7 +660,6 @@ pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi)
"sparc" => sparc::compute_abi_info(cx, self),
"sparc64" => sparc64::compute_abi_info(cx, self),
"nvptx64" => {
let abi = cx.target_spec().adjust_abi(abi, self.c_variadic);
if abi == ExternAbi::PtxKernel || abi == ExternAbi::GpuKernel {
nvptx64::compute_ptx_kernel_abi_info(cx, self)
} else {
@@ -863,70 +826,6 @@ pub fn adjust_for_rust_abi<C>(&mut self, cx: &C)
}
}
impl FromStr for Conv {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"C" => Ok(Conv::C),
"Rust" => Ok(Conv::Rust),
"RustCold" => Ok(Conv::Rust),
"ArmAapcs" => Ok(Conv::ArmAapcs),
"CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
"CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
"Msp430Intr" => Ok(Conv::Msp430Intr),
"X86Fastcall" => Ok(Conv::X86Fastcall),
"X86Intr" => Ok(Conv::X86Intr),
"X86Stdcall" => Ok(Conv::X86Stdcall),
"X86ThisCall" => Ok(Conv::X86ThisCall),
"X86VectorCall" => Ok(Conv::X86VectorCall),
"X86_64SysV" => Ok(Conv::X86_64SysV),
"X86_64Win64" => Ok(Conv::X86_64Win64),
"GpuKernel" => Ok(Conv::GpuKernel),
"AvrInterrupt" => Ok(Conv::AvrInterrupt),
"AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt),
"RiscvInterrupt(machine)" => {
Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine })
}
"RiscvInterrupt(supervisor)" => {
Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor })
}
_ => Err(format!("'{s}' is not a valid value for entry function call convention.")),
}
}
}
fn conv_to_externabi(conv: &Conv) -> ExternAbi {
match conv {
Conv::C => ExternAbi::C { unwind: false },
Conv::Rust => ExternAbi::Rust,
Conv::PreserveMost => ExternAbi::RustCold,
Conv::ArmAapcs => ExternAbi::Aapcs { unwind: false },
Conv::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,
Conv::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry,
Conv::Msp430Intr => ExternAbi::Msp430Interrupt,
Conv::GpuKernel => ExternAbi::GpuKernel,
Conv::X86Fastcall => ExternAbi::Fastcall { unwind: false },
Conv::X86Intr => ExternAbi::X86Interrupt,
Conv::X86Stdcall => ExternAbi::Stdcall { unwind: false },
Conv::X86ThisCall => ExternAbi::Thiscall { unwind: false },
Conv::X86VectorCall => ExternAbi::Vectorcall { unwind: false },
Conv::X86_64SysV => ExternAbi::SysV64 { unwind: false },
Conv::X86_64Win64 => ExternAbi::Win64 { unwind: false },
Conv::AvrInterrupt => ExternAbi::AvrInterrupt,
Conv::AvrNonBlockingInterrupt => ExternAbi::AvrNonBlockingInterrupt,
Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine } => ExternAbi::RiscvInterruptM,
Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor } => ExternAbi::RiscvInterruptS,
Conv::Cold | Conv::PreserveAll => unreachable!(),
}
}
impl Display for Conv {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", conv_to_externabi(self))
}
}
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(target_pointer_width = "64")]
mod size_asserts {
+6 -32
View File
@@ -92,38 +92,6 @@ fn to_json(&self) -> Json {
}
}
impl ToJson for crate::callconv::Conv {
fn to_json(&self) -> Json {
let buf: String;
let s = match self {
Self::C => "C",
Self::Rust => "Rust",
Self::Cold => "Cold",
Self::PreserveMost => "PreserveMost",
Self::PreserveAll => "PreserveAll",
Self::ArmAapcs => "ArmAapcs",
Self::CCmseNonSecureCall => "CCmseNonSecureCall",
Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
Self::Msp430Intr => "Msp430Intr",
Self::X86Fastcall => "X86Fastcall",
Self::X86Intr => "X86Intr",
Self::X86Stdcall => "X86Stdcall",
Self::X86ThisCall => "X86ThisCall",
Self::X86VectorCall => "X86VectorCall",
Self::X86_64SysV => "X86_64SysV",
Self::X86_64Win64 => "X86_64Win64",
Self::GpuKernel => "GpuKernel",
Self::AvrInterrupt => "AvrInterrupt",
Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt",
Self::RiscvInterrupt { kind } => {
buf = format!("RiscvInterrupt({})", kind.as_str());
&buf
}
};
Json::String(s.to_owned())
}
}
impl ToJson for TargetMetadata {
fn to_json(&self) -> Json {
json!({
@@ -140,3 +108,9 @@ fn to_json(&self) -> Json {
self.as_str().to_json()
}
}
impl ToJson for rustc_abi::CanonAbi {
fn to_json(&self) -> Json {
self.to_string().to_json()
}
}
+187
View File
@@ -0,0 +1,187 @@
use rustc_abi::{ArmCall, CanonAbi, ExternAbi, InterruptKind, X86Call};
use crate::spec::Target;
/// Mapping for ExternAbi to CanonAbi according to a Target
///
/// A maybe-transitional structure circa 2025 for hosting future experiments in
/// encapsulating arch-specific ABI lowering details to make them more testable.
#[derive(Clone, Debug)]
pub struct AbiMap {
arch: Arch,
os: OsKind,
}
#[derive(Copy, Clone, Debug)]
pub enum AbiMapping {
/// this ABI is exactly mapped for this platform
Direct(CanonAbi),
/// we don't yet warn on this, but we will
Deprecated(CanonAbi),
Invalid,
}
impl AbiMapping {
pub fn into_option(self) -> Option<CanonAbi> {
match self {
Self::Direct(abi) | Self::Deprecated(abi) => Some(abi),
Self::Invalid => None,
}
}
pub fn unwrap(self) -> CanonAbi {
self.into_option().unwrap()
}
pub fn is_mapped(self) -> bool {
self.into_option().is_some()
}
}
impl AbiMap {
pub fn from_target(target: &Target) -> Self {
// the purpose of this little exercise is to force listing what affects these mappings
let arch = match &*target.arch {
"aarch64" => Arch::Aarch64,
"amdgpu" => Arch::Amdgpu,
"arm" if target.llvm_target.starts_with("thumbv8m") => Arch::Arm(ArmVer::ThumbV8M),
"arm" => Arch::Arm(ArmVer::Other),
"avr" => Arch::Avr,
"msp430" => Arch::Msp430,
"nvptx64" => Arch::Nvptx,
"riscv32" | "riscv64" => Arch::Riscv,
"x86" => Arch::X86,
"x86_64" => Arch::X86_64,
_ => Arch::Other,
};
let os = if target.is_like_windows { OsKind::Windows } else { OsKind::Other };
AbiMap { arch, os }
}
pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMapping {
let AbiMap { os, arch } = *self;
let canon_abi = match (extern_abi, arch) {
// infallible lowerings
(ExternAbi::C { .. }, _) => CanonAbi::C,
(ExternAbi::Rust | ExternAbi::RustCall, _) => CanonAbi::Rust,
(ExternAbi::Unadjusted, _) => CanonAbi::C,
(ExternAbi::RustCold, _) if self.os == OsKind::Windows => CanonAbi::Rust,
(ExternAbi::RustCold, _) => CanonAbi::RustCold,
(ExternAbi::System { .. }, Arch::X86) if os == OsKind::Windows && !has_c_varargs => {
CanonAbi::X86(X86Call::Stdcall)
}
(ExternAbi::System { .. }, _) => CanonAbi::C,
// fallible lowerings
(ExternAbi::EfiApi, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
(ExternAbi::EfiApi, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
(ExternAbi::EfiApi, Arch::Aarch64 | Arch::Riscv | Arch::X86) => CanonAbi::C,
(ExternAbi::EfiApi, _) => return AbiMapping::Invalid,
(ExternAbi::Aapcs { .. }, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs),
(ExternAbi::Aapcs { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::CCmseNonSecureCall, Arch::Arm(ArmVer::ThumbV8M)) => {
CanonAbi::Arm(ArmCall::CCmseNonSecureCall)
}
(ExternAbi::CCmseNonSecureEntry, Arch::Arm(ArmVer::ThumbV8M)) => {
CanonAbi::Arm(ArmCall::CCmseNonSecureEntry)
}
(ExternAbi::CCmseNonSecureCall | ExternAbi::CCmseNonSecureEntry, ..) => {
return AbiMapping::Invalid;
}
(ExternAbi::Cdecl { .. }, Arch::X86) => CanonAbi::C,
(ExternAbi::Cdecl { .. }, _) => return AbiMapping::Deprecated(CanonAbi::C),
(ExternAbi::Fastcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Fastcall),
(ExternAbi::Fastcall { .. }, _) if os == OsKind::Windows => {
return AbiMapping::Deprecated(CanonAbi::C);
}
(ExternAbi::Fastcall { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::Stdcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Stdcall),
(ExternAbi::Stdcall { .. }, _) if os == OsKind::Windows => {
return AbiMapping::Deprecated(CanonAbi::C);
}
(ExternAbi::Stdcall { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::Thiscall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Thiscall),
(ExternAbi::Thiscall { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::Vectorcall { .. }, Arch::X86 | Arch::X86_64) => {
CanonAbi::X86(X86Call::Vectorcall)
}
(ExternAbi::Vectorcall { .. }, _) if os == OsKind::Windows => {
return AbiMapping::Deprecated(CanonAbi::C);
}
(ExternAbi::Vectorcall { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::SysV64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::SysV64),
(ExternAbi::Win64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::Win64),
(ExternAbi::SysV64 { .. } | ExternAbi::Win64 { .. }, _) => return AbiMapping::Invalid,
(ExternAbi::PtxKernel, Arch::Nvptx) => CanonAbi::GpuKernel,
(ExternAbi::GpuKernel, Arch::Amdgpu | Arch::Nvptx) => CanonAbi::GpuKernel,
(ExternAbi::PtxKernel | ExternAbi::GpuKernel, _) => return AbiMapping::Invalid,
(ExternAbi::AvrInterrupt, Arch::Avr) => CanonAbi::Interrupt(InterruptKind::Avr),
(ExternAbi::AvrNonBlockingInterrupt, Arch::Avr) => {
CanonAbi::Interrupt(InterruptKind::AvrNonBlocking)
}
(ExternAbi::Msp430Interrupt, Arch::Msp430) => {
CanonAbi::Interrupt(InterruptKind::Msp430)
}
(ExternAbi::RiscvInterruptM, Arch::Riscv) => {
CanonAbi::Interrupt(InterruptKind::RiscvMachine)
}
(ExternAbi::RiscvInterruptS, Arch::Riscv) => {
CanonAbi::Interrupt(InterruptKind::RiscvSupervisor)
}
(ExternAbi::X86Interrupt, Arch::X86 | Arch::X86_64) => {
CanonAbi::Interrupt(InterruptKind::X86)
}
(
ExternAbi::AvrInterrupt
| ExternAbi::AvrNonBlockingInterrupt
| ExternAbi::Msp430Interrupt
| ExternAbi::RiscvInterruptM
| ExternAbi::RiscvInterruptS
| ExternAbi::X86Interrupt,
_,
) => return AbiMapping::Invalid,
};
AbiMapping::Direct(canon_abi)
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
enum Arch {
Aarch64,
Amdgpu,
Arm(ArmVer),
Avr,
Msp430,
Nvptx,
Riscv,
X86,
X86_64,
/// Architectures which don't need other considerations for ABI lowering
Other,
}
#[derive(Debug, PartialEq, Copy, Clone)]
enum OsKind {
Windows,
Other,
}
#[derive(Debug, PartialEq, Copy, Clone)]
enum ArmVer {
ThumbV8M,
Other,
}
+17 -13
View File
@@ -2,10 +2,12 @@
use std::collections::BTreeMap;
use std::str::FromStr;
use rustc_abi::ExternAbi;
use serde_json::Value;
use super::{Target, TargetKind, TargetOptions, TargetWarnings};
use crate::json::{Json, ToJson};
use crate::spec::AbiMap;
impl Target {
/// Loads a target descriptor from a JSON object.
@@ -515,18 +517,6 @@ macro_rules! key {
}
}
} );
($key_name:ident, Conv) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
match super::Conv::from_str(s) {
Ok(c) => {
base.$key_name = c;
Some(Ok(()))
}
Err(e) => Some(Err(e))
}
})).unwrap_or(Ok(()))
} );
}
if let Some(j) = obj.remove("target-endian") {
@@ -660,9 +650,23 @@ macro_rules! key {
key!(supports_stack_protector, bool);
key!(small_data_threshold_support, SmallDataThresholdSupport)?;
key!(entry_name);
key!(entry_abi, Conv)?;
key!(supports_xray, bool);
// we're going to run `update_from_cli`, but that won't change the target's AbiMap
// FIXME: better factor the Target definition so we enforce this on a type level
let abi_map = AbiMap::from_target(&base);
if let Some(abi_str) = obj.remove("entry-abi") {
if let Json::String(abi_str) = abi_str {
match abi_str.parse::<ExternAbi>() {
Ok(abi) => base.options.entry_abi = abi_map.canonize_abi(abi, false).unwrap(),
Err(_) => return Err(format!("{abi_str} is not a valid ExternAbi")),
}
} else {
incorrect_type.push("entry-abi".to_owned())
}
}
base.update_from_cli();
base.check_consistency(TargetKind::Json)?;
+9 -113
View File
@@ -43,7 +43,7 @@
use std::{fmt, io};
use rustc_abi::{
Align, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors,
};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_fs_util::try_canonicalize;
@@ -53,15 +53,16 @@
use serde_json::Value;
use tracing::debug;
use crate::callconv::Conv;
use crate::json::{Json, ToJson};
use crate::spec::crt_objects::CrtObjects;
pub mod crt_objects;
mod abi_map;
mod base;
mod json;
pub use abi_map::AbiMap;
pub use base::apple;
pub use base::avr::ef_avr_arch;
@@ -2655,9 +2656,9 @@ pub struct TargetOptions {
/// Default value is "main"
pub entry_name: StaticCow<str>,
/// The ABI of entry function.
/// Default value is `Conv::C`, i.e. C call convention
pub entry_abi: Conv,
/// The ABI of the entry function.
/// Default value is `CanonAbi::C`
pub entry_abi: CanonAbi,
/// Whether the target supports XRay instrumentation.
pub supports_xray: bool,
@@ -2888,7 +2889,7 @@ fn default() -> TargetOptions {
generate_arange_section: true,
supports_stack_protector: true,
entry_name: "main".into(),
entry_abi: Conv::C,
entry_abi: CanonAbi::C,
supports_xray: false,
small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch,
}
@@ -2914,114 +2915,9 @@ fn deref_mut(&mut self) -> &mut Self::Target {
}
impl Target {
/// Given a function ABI, turn it into the correct ABI for this target.
pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi {
use ExternAbi::*;
match abi {
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
// `__stdcall` only applies on x86 and on non-variadic functions:
// https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
System { unwind } => {
if self.is_like_windows && self.arch == "x86" && !c_variadic {
Stdcall { unwind }
} else {
C { unwind }
}
}
EfiApi => {
if self.arch == "arm" {
Aapcs { unwind: false }
} else if self.arch == "x86_64" {
Win64 { unwind: false }
} else {
C { unwind: false }
}
}
// See commentary in `is_abi_supported`.
Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => {
if self.arch == "x86" { abi } else { C { unwind } }
}
Vectorcall { unwind } => {
if ["x86", "x86_64"].contains(&&*self.arch) {
abi
} else {
C { unwind }
}
}
// The Windows x64 calling convention we use for `extern "Rust"`
// <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
// expects the callee to save `xmm6` through `xmm15`, but `PreserveMost`
// (that we use by default for `extern "rust-cold"`) doesn't save any of those.
// So to avoid bloating callers, just use the Rust convention here.
RustCold if self.is_like_windows && self.arch == "x86_64" => Rust,
abi => abi,
}
}
pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
use ExternAbi::*;
match abi {
Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => {
true
}
EfiApi => {
["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
}
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs { .. } => "arm" == self.arch,
CCmseNonSecureCall | CCmseNonSecureEntry => {
["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
.contains(&&self.llvm_target[..])
}
Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
PtxKernel => self.arch == "nvptx64",
GpuKernel => ["amdgpu", "nvptx64"].contains(&&self.arch[..]),
Msp430Interrupt => self.arch == "msp430",
RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]),
AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr",
Thiscall { .. } => self.arch == "x86",
// On windows these fall-back to platform native calling convention (C) when the
// architecture is not supported.
//
// This is I believe a historical accident that has occurred as part of Microsoft
// striving to allow most of the code to "just" compile when support for 64-bit x86
// was added and then later again, when support for ARM architectures was added.
//
// This is well documented across MSDN. Support for this in Rust has been added in
// #54576. This makes much more sense in context of Microsoft's C++ than it does in
// Rust, but there isn't much leeway remaining here to change it back at the time this
// comment has been written.
//
// Following are the relevant excerpts from the MSDN documentation.
//
// > The __vectorcall calling convention is only supported in native code on x86 and
// x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above.
// > ...
// > On ARM machines, __vectorcall is accepted and ignored by the compiler.
//
// -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160
//
// > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler;
//
// -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160
//
// > In most cases, keywords or compiler switches that specify an unsupported
// > convention on a particular platform are ignored, and the platform default
// > convention is used.
//
// -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions
Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true,
// Outside of Windows we want to only support these calling conventions for the
// architectures for which these calling conventions are actually well defined.
Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true,
Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true,
// Reject these calling conventions everywhere else.
Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => false,
}
let abi_map = AbiMap::from_target(self);
abi_map.canonize_abi(abi, false).is_mapped()
}
/// Minimum integer size in bits that this target can perform atomic
@@ -5,7 +5,8 @@
// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with
// LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features.
use crate::callconv::Conv;
use rustc_abi::{CanonAbi, X86Call};
use crate::spec::{RustcAbi, Target, TargetMetadata, base};
pub(crate) fn target() -> Target {
@@ -13,7 +14,7 @@ pub(crate) fn target() -> Target {
base.cpu = "x86-64".into();
base.plt_by_default = false;
base.max_atomic_width = Some(64);
base.entry_abi = Conv::X86_64Win64;
base.entry_abi = CanonAbi::X86(X86Call::Win64);
// We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to
// enable these CPU features explicitly before their first use, otherwise their instructions
+2 -2
View File
@@ -72,8 +72,6 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds
trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment
trait_selection_await_both_futures = consider `await`ing on both `Future`s
trait_selection_await_future = consider `await`ing on the `Future`
trait_selection_await_note = calling an async function returns a future
@@ -123,6 +121,8 @@ trait_selection_closure_kind_requirement = the requirement to implement `{$trait
trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait
trait_selection_consider_specifying_length = consider specifying the actual array length
trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment
trait_selection_data_flows = ...but data{$label_var1_exists ->
[true] {" "}from `{$label_var1}`
*[false] {""}
@@ -42,9 +42,7 @@
use crate::error_reporting::TypeErrCtxt;
use crate::error_reporting::infer::TyCategory;
use crate::error_reporting::traits::report_dyn_incompatibility;
use crate::errors::{
AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch,
};
use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn};
use crate::infer::{self, InferCtxt, InferCtxtExt as _};
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::{
@@ -886,9 +884,18 @@ fn emit_specialized_closure_kind_error(
// is unimplemented is because async closures don't implement `Fn`/`FnMut`
// if they have captures.
if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce {
let mut err = self.dcx().create_err(AsyncClosureNotFn {
let coro_kind = match self
.tcx
.coroutine_kind(self.tcx.coroutine_for_closure(closure_def_id))
.unwrap()
{
rustc_hir::CoroutineKind::Desugared(desugaring, _) => desugaring.to_string(),
coro => coro.to_string(),
};
let mut err = self.dcx().create_err(CoroClosureNotFn {
span: self.tcx.def_span(closure_def_id),
kind: expected_kind.as_str(),
coro_kind,
});
self.note_obligation_cause(&mut err, &obligation);
return Some(err.emit());
+3 -2
View File
@@ -201,11 +201,12 @@ pub struct ClosureFnMutLabel {
}
#[derive(Diagnostic)]
#[diag(trait_selection_async_closure_not_fn)]
pub(crate) struct AsyncClosureNotFn {
#[diag(trait_selection_coro_closure_not_fn)]
pub(crate) struct CoroClosureNotFn {
#[primary_span]
pub span: Span,
pub kind: &'static str,
pub coro_kind: String,
}
#[derive(Diagnostic)]
@@ -11,7 +11,7 @@
use hir::LangItem;
use hir::def_id::DefId;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
@@ -438,6 +438,7 @@ fn assemble_closure_candidates(
}
}
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_async_closure_candidates(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
@@ -446,15 +447,30 @@ fn assemble_async_closure_candidates(
let goal_kind =
self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
match *obligation.self_ty().skip_binder().kind() {
ty::CoroutineClosure(_, args) => {
ty::CoroutineClosure(def_id, args) => {
if let Some(closure_kind) =
args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
&& !closure_kind.extends(goal_kind)
{
return;
}
candidates.vec.push(AsyncClosureCandidate);
// Make sure this is actually an async closure.
let Some(coroutine_kind) =
self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
else {
bug!("coroutine with no kind");
};
debug!(?coroutine_kind);
match coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
candidates.vec.push(AsyncClosureCandidate);
}
_ => (),
}
}
// Closures and fn pointers implement `AsyncFn*` if their return types
// implement `Future`, which is checked later.
+3 -41
View File
@@ -13,7 +13,7 @@
use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId;
use rustc_target::callconv::{
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, RiscvInterruptKind,
AbiMap, ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, FnAbi, PassMode,
};
use tracing::debug;
@@ -240,45 +240,6 @@ fn fn_sig_for_fn_abi<'tcx>(
}
}
#[inline]
fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv {
use rustc_abi::ExternAbi::*;
match tcx.sess.target.adjust_abi(abi, c_variadic) {
Rust | RustCall => Conv::Rust,
// This is intentionally not using `Conv::Cold`, as that has to preserve
// even SIMD registers, which is generally not a good trade-off.
RustCold => Conv::PreserveMost,
// It's the ABI's job to select this, not ours.
System { .. } => bug!("system abi should be selected elsewhere"),
EfiApi => bug!("eficall abi should be selected elsewhere"),
Stdcall { .. } => Conv::X86Stdcall,
Fastcall { .. } => Conv::X86Fastcall,
Vectorcall { .. } => Conv::X86VectorCall,
Thiscall { .. } => Conv::X86ThisCall,
C { .. } => Conv::C,
Unadjusted => Conv::C,
Win64 { .. } => Conv::X86_64Win64,
SysV64 { .. } => Conv::X86_64SysV,
Aapcs { .. } => Conv::ArmAapcs,
CCmseNonSecureCall => Conv::CCmseNonSecureCall,
CCmseNonSecureEntry => Conv::CCmseNonSecureEntry,
PtxKernel => Conv::GpuKernel,
Msp430Interrupt => Conv::Msp430Intr,
X86Interrupt => Conv::X86Intr,
GpuKernel => Conv::GpuKernel,
AvrInterrupt => Conv::AvrInterrupt,
AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine },
RiscvInterruptS => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor },
// These API constants ought to be more specific...
Cdecl { .. } => Conv::C,
}
}
fn fn_abi_of_fn_ptr<'tcx>(
tcx: TyCtxt<'tcx>,
query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
@@ -529,7 +490,8 @@ fn fn_abi_new_uncached<'tcx>(
};
let sig = tcx.normalize_erasing_regions(cx.typing_env, sig);
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
let abi_map = AbiMap::from_target(&tcx.sess.target);
let conv = abi_map.canonize_abi(sig.abi, sig.c_variadic).unwrap();
let mut inputs = sig.inputs();
let extra_args = if sig.abi == ExternAbi::RustCall {
-1
View File
@@ -32,7 +32,6 @@ optimize_for_size = ["core/optimize_for_size"]
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(bootstrap)',
'cfg(no_global_oom_handling)',
'cfg(no_rc)',
'cfg(no_sync)',
-1
View File
@@ -66,7 +66,6 @@
)]
#![doc(cfg_hide(
not(test),
not(any(test, bootstrap)),
no_global_oom_handling,
not(no_global_oom_handling),
not(no_rc),
-1
View File
@@ -39,7 +39,6 @@ harness = false
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(bootstrap)',
'cfg(no_global_oom_handling)',
'cfg(no_rc)',
'cfg(no_sync)',
-1
View File
@@ -29,7 +29,6 @@ debug_typeid = []
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(bootstrap)',
'cfg(no_fp_fmt_parse)',
# core use #[path] imports to portable-simd `core_simd` crate
# and to stdarch `core_arch` crate which messes-up with Cargo list
+8 -40
View File
@@ -413,38 +413,7 @@ pub unsafe fn atomic_cxchgweak_release_acquire<T: Copy>(
/// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`].
#[rustc_intrinsic]
#[rustc_nounwind]
#[cfg(not(bootstrap))]
pub unsafe fn atomic_load<T: Copy, const ORD: AtomicOrdering>(src: *const T) -> T;
/// Loads the current value of the pointer.
/// `T` must be an integer or pointer type.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `load` method by passing
/// [`Ordering::SeqCst`] as the `order`. For example, [`AtomicBool::load`].
#[rustc_intrinsic]
#[rustc_nounwind]
#[cfg(bootstrap)]
pub unsafe fn atomic_load_seqcst<T: Copy>(src: *const T) -> T;
/// Loads the current value of the pointer.
/// `T` must be an integer or pointer type.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `load` method by passing
/// [`Ordering::Acquire`] as the `order`. For example, [`AtomicBool::load`].
#[rustc_intrinsic]
#[rustc_nounwind]
#[cfg(bootstrap)]
pub unsafe fn atomic_load_acquire<T: Copy>(src: *const T) -> T;
/// Loads the current value of the pointer.
/// `T` must be an integer or pointer type.
///
/// The stabilized version of this intrinsic is available on the
/// [`atomic`] types via the `load` method by passing
/// [`Ordering::Relaxed`] as the `order`. For example, [`AtomicBool::load`].
#[rustc_intrinsic]
#[rustc_nounwind]
#[cfg(bootstrap)]
pub unsafe fn atomic_load_relaxed<T: Copy>(src: *const T) -> T;
/// Stores the value at the specified memory location.
/// `T` must be an integer or pointer type.
@@ -1767,7 +1736,6 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
/// - `index < PtrMetadata(slice_ptr)`, so the indexing is in-bounds for the slice
/// - the resulting offsetting is in-bounds of the allocated object, which is
/// always the case for references, but needs to be upheld manually for pointers
#[cfg(not(bootstrap))]
#[rustc_nounwind]
#[rustc_intrinsic]
pub const unsafe fn slice_get_unchecked<
@@ -3710,7 +3678,7 @@ pub const fn aggregate_raw_ptr<P: bounds::BuiltinDeref, D, M>(data: D, meta: M)
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn minimumf16(x: f16, y: f16) -> f16 {
if x < y {
x
@@ -3731,7 +3699,7 @@ pub const fn minimumf16(x: f16, y: f16) -> f16 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn minimumf32(x: f32, y: f32) -> f32 {
if x < y {
x
@@ -3752,7 +3720,7 @@ pub const fn minimumf32(x: f32, y: f32) -> f32 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn minimumf64(x: f64, y: f64) -> f64 {
if x < y {
x
@@ -3773,7 +3741,7 @@ pub const fn minimumf64(x: f64, y: f64) -> f64 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn minimumf128(x: f128, y: f128) -> f128 {
if x < y {
x
@@ -3848,7 +3816,7 @@ pub const fn minimumf128(x: f128, y: f128) -> f128 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn maximumf16(x: f16, y: f16) -> f16 {
if x > y {
x
@@ -3868,7 +3836,7 @@ pub const fn maximumf16(x: f16, y: f16) -> f16 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn maximumf32(x: f32, y: f32) -> f32 {
if x > y {
x
@@ -3888,7 +3856,7 @@ pub const fn maximumf32(x: f32, y: f32) -> f32 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn maximumf64(x: f64, y: f64) -> f64 {
if x > y {
x
@@ -3908,7 +3876,7 @@ pub const fn maximumf64(x: f64, y: f64) -> f64 {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
#[rustc_intrinsic]
pub const fn maximumf128(x: f128, y: f128) -> f128 {
if x > y {
x
+2
View File
@@ -420,6 +420,8 @@ fn $fold<AAA, FFF>(mut self, init: AAA, fold: FFF) -> AAA
issue = "42168"
)]
pub use self::range::Step;
#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
pub use self::sources::iter;
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::sources::{Empty, empty};
#[unstable(
+3
View File
@@ -1,6 +1,7 @@
mod empty;
mod from_coroutine;
mod from_fn;
mod generator;
mod once;
mod once_with;
mod repeat;
@@ -18,6 +19,8 @@
pub use self::from_coroutine::{FromCoroutine, from_coroutine};
#[stable(feature = "iter_from_fn", since = "1.34.0")]
pub use self::from_fn::{FromFn, from_fn};
#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
pub use self::generator::iter;
#[stable(feature = "iter_once", since = "1.2.0")]
pub use self::once::{Once, once};
#[stable(feature = "iter_once_with", since = "1.43.0")]
@@ -0,0 +1,29 @@
/// Creates a new closure that returns an iterator where each iteration steps the given
/// generator to the next `yield` statement.
///
/// Similar to [`iter::from_fn`], but allows arbitrary control flow.
///
/// [`iter::from_fn`]: crate::iter::from_fn
///
/// # Examples
///
/// ```
/// #![feature(iter_macro, coroutines)]
/// # #[cfg(not(bootstrap))]
/// # {
///
/// let it = std::iter::iter!{|| {
/// yield 1;
/// yield 2;
/// yield 3;
/// } }();
/// let v: Vec<_> = it.collect();
/// assert_eq!(v, [1, 2, 3]);
/// # }
/// ```
#[unstable(feature = "iter_macro", issue = "none", reason = "generators are unstable")]
#[allow_internal_unstable(coroutines, iter_from_coroutine)]
#[cfg_attr(not(bootstrap), rustc_builtin_macro)]
pub macro iter($($t:tt)*) {
/* compiler-builtin */
}
-2
View File
@@ -187,7 +187,6 @@
//
// Target features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(avx512_target_feature))]
#![feature(aarch64_unstable_target_feature)]
#![feature(arm_target_feature)]
#![feature(hexagon_target_feature)]
@@ -225,7 +224,6 @@ pub mod assert_matches {
// We don't export this through #[macro_export] for now, to avoid breakage.
#[unstable(feature = "autodiff", issue = "124509")]
#[cfg(not(bootstrap))]
/// Unstable module containing the unstable `autodiff` macro.
pub mod autodiff {
#[unstable(feature = "autodiff", issue = "124509")]
-2
View File
@@ -1533,7 +1533,6 @@ macro_rules! include {
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[rustc_builtin_macro]
#[cfg(not(bootstrap))]
pub macro autodiff_forward($item:item) {
/* compiler built-in */
}
@@ -1552,7 +1551,6 @@ macro_rules! include {
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[rustc_builtin_macro]
#[cfg(not(bootstrap))]
pub macro autodiff_reverse($item:item) {
/* compiler built-in */
}
-1
View File
@@ -1092,7 +1092,6 @@
#[rustc_pub_transparent]
#[derive(Copy, Clone)]
pub struct Pin<Ptr> {
/// Only public for bootstrap.
pointer: Ptr,
}
+4 -53
View File
@@ -1,6 +1,5 @@
//! Indexing implementations for `[T]`.
#[cfg(not(bootstrap))]
use crate::intrinsics::slice_get_unchecked;
use crate::panic::const_panic;
use crate::ub_checks::assert_unsafe_precondition;
@@ -85,22 +84,6 @@ const fn slice_end_index_overflow_fail() -> ! {
// Both the safe and unsafe public methods share these helpers,
// which use intrinsics directly to get *no* extra checks.
#[cfg(bootstrap)]
#[inline(always)]
const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
let ptr = ptr as *const T;
// SAFETY: The caller already checked these preconditions
unsafe { crate::intrinsics::offset(ptr, index) }
}
#[cfg(bootstrap)]
#[inline(always)]
const unsafe fn get_mut_noubcheck<T>(ptr: *mut [T], index: usize) -> *mut T {
let ptr = ptr as *mut T;
// SAFETY: The caller already checked these preconditions
unsafe { crate::intrinsics::offset(ptr, index) }
}
#[inline(always)]
const unsafe fn get_offset_len_noubcheck<T>(
ptr: *const [T],
@@ -231,16 +214,8 @@ unsafe impl<T> SliceIndex<[T]> for usize {
#[inline]
fn get(self, slice: &[T]) -> Option<&T> {
if self < slice.len() {
#[cfg(bootstrap)]
// SAFETY: `self` is checked to be in bounds.
unsafe {
Some(&*get_noubcheck(slice, self))
}
#[cfg(not(bootstrap))]
// SAFETY: `self` is checked to be in bounds.
unsafe {
Some(slice_get_unchecked(slice, self))
}
unsafe { Some(slice_get_unchecked(slice, self)) }
} else {
None
}
@@ -249,16 +224,8 @@ fn get(self, slice: &[T]) -> Option<&T> {
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
if self < slice.len() {
#[cfg(bootstrap)]
// SAFETY: `self` is checked to be in bounds.
unsafe {
Some(&mut *get_mut_noubcheck(slice, self))
}
#[cfg(not(bootstrap))]
// SAFETY: `self` is checked to be in bounds.
unsafe {
Some(slice_get_unchecked(slice, self))
}
unsafe { Some(slice_get_unchecked(slice, self)) }
} else {
None
}
@@ -280,14 +247,7 @@ unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
// Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
// precondition of this function twice.
crate::intrinsics::assume(self < slice.len());
#[cfg(bootstrap)]
{
get_noubcheck(slice, self)
}
#[cfg(not(bootstrap))]
{
slice_get_unchecked(slice, self)
}
slice_get_unchecked(slice, self)
}
}
@@ -300,16 +260,7 @@ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
(this: usize = self, len: usize = slice.len()) => this < len
);
// SAFETY: see comments for `get_unchecked` above.
unsafe {
#[cfg(bootstrap)]
{
get_mut_noubcheck(slice, self)
}
#[cfg(not(bootstrap))]
{
slice_get_unchecked(slice, self)
}
}
unsafe { slice_get_unchecked(slice, self) }
}
#[inline]
-17
View File
@@ -3822,23 +3822,6 @@ unsafe fn atomic_store<T: Copy>(dst: *mut T, val: T, order: Ordering) {
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[cfg(bootstrap)]
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
unsafe {
match order {
Relaxed => intrinsics::atomic_load_relaxed(dst),
Acquire => intrinsics::atomic_load_acquire(dst),
SeqCst => intrinsics::atomic_load_seqcst(dst),
Release => panic!("there is no such thing as a release load"),
AcqRel => panic!("there is no such thing as an acquire-release load"),
}
}
}
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[cfg(not(bootstrap))]
unsafe fn atomic_load<T: Copy>(dst: *const T, order: Ordering) -> T {
use intrinsics::AtomicOrdering;
// SAFETY: the caller must uphold the safety contract for `atomic_load`.
-6
View File
@@ -951,7 +951,6 @@ fn div_euclid() {
assert!(<$fty>::NAN.div_euclid(<$fty>::INFINITY).is_nan());
}
#[test]
#[cfg(not(bootstrap))]
fn floor() {
$fassert!((0.0 as $fty).floor(), 0.0);
$fassert!((0.0 as $fty).floor().is_sign_positive());
@@ -969,7 +968,6 @@ fn floor() {
$fassert!(<$fty>::NEG_INFINITY.floor(), <$fty>::NEG_INFINITY);
}
#[test]
#[cfg(not(bootstrap))]
fn ceil() {
$fassert!((0.0 as $fty).ceil(), 0.0);
$fassert!((0.0 as $fty).ceil().is_sign_positive());
@@ -986,7 +984,6 @@ fn ceil() {
$fassert!(<$fty>::NEG_INFINITY.ceil(), <$fty>::NEG_INFINITY);
}
#[test]
#[cfg(not(bootstrap))]
fn round() {
$fassert!((0.0 as $fty).round(), 0.0);
$fassert!((0.0 as $fty).round().is_sign_positive());
@@ -1003,7 +1000,6 @@ fn round() {
$fassert!(<$fty>::NEG_INFINITY.round(), <$fty>::NEG_INFINITY);
}
#[test]
#[cfg(not(bootstrap))]
fn round_ties_even() {
$fassert!((0.0 as $fty).round_ties_even(), 0.0);
$fassert!((0.0 as $fty).round_ties_even().is_sign_positive());
@@ -1022,7 +1018,6 @@ fn round_ties_even() {
$fassert!(<$fty>::NEG_INFINITY.round_ties_even(), <$fty>::NEG_INFINITY);
}
#[test]
#[cfg(not(bootstrap))]
fn trunc() {
$fassert!((0.0 as $fty).trunc(), 0.0);
$fassert!((0.0 as $fty).trunc().is_sign_positive());
@@ -1041,7 +1036,6 @@ fn trunc() {
$fassert!(<$fty>::NEG_INFINITY.trunc(), <$fty>::NEG_INFINITY);
}
#[test]
#[cfg(not(bootstrap))]
fn fract() {
$fassert!((0.0 as $fty).fract(), 0.0);
$fassert!((0.0 as $fty).fract().is_sign_positive());
-1
View File
@@ -157,7 +157,6 @@ test = true
[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = [
'cfg(bootstrap)',
# std use #[path] imports to portable-simd `std_float` crate
# and to the `backtrace` crate which messes-up with Cargo list
# of declared features, we therefor expect any feature cfg
+2 -8
View File
@@ -235,12 +235,7 @@
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
)]
#![doc(rust_logo)]
#![doc(cfg_hide(
not(test),
not(any(test, bootstrap)),
no_global_oom_handling,
not(no_global_oom_handling)
))]
#![doc(cfg_hide(not(test), no_global_oom_handling, not(no_global_oom_handling)))]
// Don't link to std. We are std.
#![no_std]
// Tell the compiler to link to either panic_abort or panic_unwind
@@ -276,12 +271,12 @@
// tidy-alphabetical-start
// stabilization was reverted after it hit beta
#![cfg_attr(not(bootstrap), feature(autodiff))]
#![feature(alloc_error_handler)]
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(asm_experimental_arch)]
#![feature(autodiff)]
#![feature(cfg_sanitizer_cfi)]
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
@@ -641,7 +636,6 @@ pub mod simd {
}
#[unstable(feature = "autodiff", issue = "124509")]
#[cfg(not(bootstrap))]
/// This module provides support for automatic differentiation.
pub mod autodiff {
/// This macro handles automatic differentiation.
+3 -1
View File
@@ -25,7 +25,9 @@ pub fn pthread_key_create(
#[inline]
pub fn create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
let mut key = 0;
assert_eq!(unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) }, 0);
if unsafe { libc::pthread_key_create(&mut key, mem::transmute(dtor)) } != 0 {
rtabort!("out of TLS keys");
}
key
}
@@ -81,15 +81,10 @@ unsafe fn init(&'static self) -> Key {
} else {
let key = unsafe { c::TlsAlloc() };
if key == c::TLS_OUT_OF_INDEXES {
// Wakeup the waiting threads before panicking to avoid deadlock.
unsafe {
c::InitOnceComplete(
self.once.get(),
c::INIT_ONCE_INIT_FAILED,
ptr::null_mut(),
);
}
panic!("out of TLS indexes");
// Since we abort the process, there is no need to wake up
// the waiting threads. If this were a panic, the wakeup
// would need to occur first in order to avoid deadlock.
rtabort!("out of TLS indexes");
}
unsafe {
@@ -112,7 +107,9 @@ unsafe fn init(&'static self) -> Key {
// If there is no destructor to clean up, we can use racy initialization.
let key = unsafe { c::TlsAlloc() };
assert_ne!(key, c::TLS_OUT_OF_INDEXES, "out of TLS indexes");
if key == c::TLS_OUT_OF_INDEXES {
rtabort!("out of TLS indexes");
}
match self.key.compare_exchange(0, key + 1, AcqRel, Acquire) {
Ok(_) => key,
@@ -68,7 +68,7 @@ fn main() {
// This should be linted, since `suppress-restriction-lint-in-const` default is false.
const { &ARR[idx4()] };
//~^ ERROR: indexing may panic
//~| ERROR: evaluation of `main
//~| ERROR: index out of bounds
let y = &x;
// Ok, referencing shouldn't affect this lint. See the issue 6021
@@ -9,11 +9,11 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re
= note: `-D clippy::indexing-slicing` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]`
error[E0080]: evaluation of `main::{constant#3}` failed
error[E0080]: index out of bounds: the length is 2 but the index is 4
--> tests/ui/indexing_slicing_index.rs:69:14
|
LL | const { &ARR[idx4()] };
| ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
| ^^^^^^^^^^^ evaluation of `main::{constant#3}` failed here
note: erroneous constant encountered
--> tests/ui/indexing_slicing_index.rs:69:5
+7 -7
View File
@@ -3,7 +3,7 @@
use std::{cmp, iter};
use rand::RngCore;
use rustc_abi::{Align, ExternAbi, FieldIdx, FieldsShape, Size, Variants};
use rustc_abi::{Align, CanonAbi, ExternAbi, FieldIdx, FieldsShape, Size, Variants};
use rustc_apfloat::Float;
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_hir::Safety;
@@ -18,7 +18,7 @@
use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol};
use rustc_symbol_mangling::mangle_internal_symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -936,11 +936,11 @@ fn read_wchar_t_str(&self, ptr: Pointer) -> InterpResult<'tcx, Vec<u32>> {
fn check_callconv<'a>(
&self,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: Conv,
exp_abi: CanonAbi,
) -> InterpResult<'a, ()> {
if fn_abi.conv != exp_abi {
throw_ub_format!(
"calling a function with calling convention {exp_abi} using caller calling convention {}",
r#"calling a function with calling convention "{exp_abi}" using caller calling convention "{}""#,
fn_abi.conv
);
}
@@ -973,7 +973,7 @@ fn frame_in_std(&self) -> bool {
fn check_abi_and_shim_symbol_clash(
&mut self,
abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: Conv,
exp_abi: CanonAbi,
link_name: Symbol,
) -> InterpResult<'tcx, ()> {
self.check_callconv(abi, exp_abi)?;
@@ -998,7 +998,7 @@ fn check_abi_and_shim_symbol_clash(
fn check_shim<'a, const N: usize>(
&mut self,
abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: Conv,
exp_abi: CanonAbi,
link_name: Symbol,
args: &'a [OpTy<'tcx>],
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> {
@@ -1098,7 +1098,7 @@ fn check_shim_abi<'a, const N: usize>(
fn check_shim_variadic<'a, const N: usize>(
&mut self,
abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: Conv,
exp_abi: CanonAbi,
link_name: Symbol,
args: &'a [OpTy<'tcx>],
) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])>
+4 -3
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_middle::mir::BinOp;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -19,7 +20,7 @@ fn emulate_aarch64_intrinsic(
let unprefixed_name = link_name.as_str().strip_prefix("llvm.aarch64.").unwrap();
match unprefixed_name {
"isb" => {
let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
let [arg] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let arg = this.read_scalar(arg)?.to_i32()?;
match arg {
// SY ("full system scope")
@@ -37,7 +38,7 @@ fn emulate_aarch64_intrinsic(
// `left` input, the second half of the output from the `right` input.
// https://developer.arm.com/architectures/instruction-sets/intrinsics/vpmaxq_u8
"neon.umaxp.v16i8" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
+6 -6
View File
@@ -1,8 +1,8 @@
use rustc_abi::Size;
use rustc_abi::{CanonAbi, Size};
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_middle::ty::{self, Instance, Ty};
use rustc_span::{BytePos, Loc, Symbol, hygiene};
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -16,7 +16,7 @@ fn handle_miri_backtrace_size(
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let [flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [flags] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?;
if flags != 0 {
@@ -38,7 +38,7 @@ fn handle_miri_get_backtrace(
let ptr_ty = this.machine.layouts.mut_raw_ptr.ty;
let ptr_layout = this.layout_of(ptr_ty)?;
let [flags, buf] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [flags, buf] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?;
let buf_place = this.deref_pointer_as(buf, ptr_layout)?;
@@ -118,7 +118,7 @@ fn handle_miri_resolve_frame(
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let [ptr, flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr, flags] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?;
@@ -190,7 +190,7 @@ fn handle_miri_resolve_frame_names(
let this = self.eval_context_mut();
let [ptr, flags, name_ptr, filename_ptr] =
this.check_shim(abi, Conv::Rust, link_name, args)?;
this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?;
if flags != 0 {
+40 -39
View File
@@ -2,7 +2,7 @@
use std::io::Write;
use std::path::Path;
use rustc_abi::{Align, AlignFromBytesError, Size};
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
use rustc_apfloat::Float;
use rustc_ast::expand::allocator::alloc_error_handler_name;
use rustc_hir::def::DefKind;
@@ -12,7 +12,7 @@
use rustc_middle::ty::{Instance, Ty};
use rustc_middle::{mir, ty};
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use self::helpers::{ToHost, ToSoft};
use super::alloc::EvalContextExt as _;
@@ -250,7 +250,7 @@ fn emulate_foreign_item_inner(
// When adding a new shim, you should follow the following pattern:
// ```
// "shim_name" => {
// let [arg1, arg2, arg3] = this.check_shim(abi, Conv::::C , link_name, args)?;
// let [arg1, arg2, arg3] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
// let result = this.shim_name(arg1, arg2, arg3)?;
// this.write_scalar(result, dest)?;
// }
@@ -288,16 +288,16 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// Miri-specific extern functions
"miri_start_unwind" => {
let [payload] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [payload] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind);
}
"miri_run_provenance_gc" => {
let [] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
this.run_provenance_gc();
}
"miri_get_alloc_id" => {
let [ptr] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| {
err_machine_stop!(TerminationInfo::Abort(format!(
@@ -307,7 +307,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
}
"miri_print_borrow_state" => {
let [id, show_unnamed] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [id, show_unnamed] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let id = this.read_scalar(id)?.to_u64()?;
let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?;
if let Some(id) = std::num::NonZero::new(id).map(AllocId)
@@ -321,7 +321,8 @@ fn emulate_foreign_item_inner(
"miri_pointer_name" => {
// This associates a name to a tag. Very useful for debugging, and also makes
// tests more strict.
let [ptr, nth_parent, name] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr, nth_parent, name] =
this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let nth_parent = this.read_scalar(nth_parent)?.to_u8()?;
let name = this.read_immediate(name)?;
@@ -334,7 +335,7 @@ fn emulate_foreign_item_inner(
this.give_pointer_debug_name(ptr, nth_parent, &name)?;
}
"miri_static_root" => {
let [ptr] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?;
if offset != Size::ZERO {
@@ -345,7 +346,7 @@ fn emulate_foreign_item_inner(
this.machine.static_roots.push(alloc_id);
}
"miri_host_to_target_path" => {
let [ptr, out, out_size] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr, out, out_size] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let out = this.read_pointer(out)?;
let out_size = this.read_scalar(out_size)?.to_target_usize(this)?;
@@ -381,7 +382,7 @@ fn emulate_foreign_item_inner(
// Writes some bytes to the interpreter's stdout/stderr. See the
// README for details.
"miri_write_to_stdout" | "miri_write_to_stderr" => {
let [msg] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [msg] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let msg = this.read_immediate(msg)?;
let msg = this.read_byte_slice(&msg)?;
// Note: we're ignoring errors writing to host stdout/stderr.
@@ -395,7 +396,7 @@ fn emulate_foreign_item_inner(
"miri_promise_symbolic_alignment" => {
use rustc_abi::AlignFromBytesError;
let [ptr, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [ptr, align] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let align = this.read_target_usize(align)?;
if !align.is_power_of_two() {
@@ -436,12 +437,12 @@ fn emulate_foreign_item_inner(
// Aborting the process.
"exit" => {
let [code] = this.check_shim(abi, Conv::C, link_name, args)?;
let [code] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let code = this.read_scalar(code)?.to_i32()?;
throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false });
}
"abort" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
throw_machine_stop!(TerminationInfo::Abort(
"the program aborted execution".to_owned()
))
@@ -449,7 +450,7 @@ fn emulate_foreign_item_inner(
// Standard C allocation
"malloc" => {
let [size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let size = this.read_target_usize(size)?;
if size <= this.max_size_of_val().bytes() {
let res = this.malloc(size, AllocInit::Uninit)?;
@@ -463,7 +464,7 @@ fn emulate_foreign_item_inner(
}
}
"calloc" => {
let [items, elem_size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [items, elem_size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let items = this.read_target_usize(items)?;
let elem_size = this.read_target_usize(elem_size)?;
if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) {
@@ -478,12 +479,12 @@ fn emulate_foreign_item_inner(
}
}
"free" => {
let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
this.free(ptr)?;
}
"realloc" => {
let [old_ptr, new_size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [old_ptr, new_size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let old_ptr = this.read_pointer(old_ptr)?;
let new_size = this.read_target_usize(new_size)?;
if new_size <= this.max_size_of_val().bytes() {
@@ -503,7 +504,7 @@ fn emulate_foreign_item_inner(
let default = |ecx: &mut MiriInterpCx<'tcx>| {
// Only call `check_shim` when `#[global_allocator]` isn't used. When that
// macro is used, we act like no shim exists, so that the exported function can run.
let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
let [size, align] = ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let size = ecx.read_target_usize(size)?;
let align = ecx.read_target_usize(align)?;
@@ -536,7 +537,7 @@ fn emulate_foreign_item_inner(
return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let [size, align] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let size = this.read_target_usize(size)?;
let align = this.read_target_usize(align)?;
@@ -558,7 +559,7 @@ fn emulate_foreign_item_inner(
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [ptr, old_size, align] =
ecx.check_shim(abi, Conv::Rust, link_name, args)?;
ecx.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = ecx.read_pointer(ptr)?;
let old_size = ecx.read_target_usize(old_size)?;
let align = ecx.read_target_usize(align)?;
@@ -589,7 +590,7 @@ fn emulate_foreign_item_inner(
// See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case.
let [ptr, old_size, align, new_size] =
this.check_shim(abi, Conv::Rust, link_name, args)?;
this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let old_size = this.read_target_usize(old_size)?;
let align = this.read_target_usize(align)?;
@@ -613,7 +614,7 @@ fn emulate_foreign_item_inner(
// C memory handling functions
"memcmp" => {
let [left, right, n] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, n] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let left = this.read_pointer(left)?;
let right = this.read_pointer(right)?;
let n = Size::from_bytes(this.read_target_usize(n)?);
@@ -637,7 +638,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(Scalar::from_i32(result), dest)?;
}
"memrchr" => {
let [ptr, val, num] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, val, num] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_target_usize(num)?;
@@ -663,7 +664,7 @@ fn emulate_foreign_item_inner(
}
}
"memchr" => {
let [ptr, val, num] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, val, num] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_target_usize(num)?;
@@ -686,7 +687,7 @@ fn emulate_foreign_item_inner(
}
}
"strlen" => {
let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_c_str(ptr)?.len();
@@ -696,7 +697,7 @@ fn emulate_foreign_item_inner(
)?;
}
"wcslen" => {
let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_wchar_t_str(ptr)?.len();
@@ -706,7 +707,7 @@ fn emulate_foreign_item_inner(
)?;
}
"memcpy" => {
let [ptr_dest, ptr_src, n] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr_dest, ptr_src, n] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr_dest = this.read_pointer(ptr_dest)?;
let ptr_src = this.read_pointer(ptr_src)?;
let n = this.read_target_usize(n)?;
@@ -720,7 +721,7 @@ fn emulate_foreign_item_inner(
this.write_pointer(ptr_dest, dest)?;
}
"strcpy" => {
let [ptr_dest, ptr_src] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr_dest, ptr_src] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr_dest = this.read_pointer(ptr_dest)?;
let ptr_src = this.read_pointer(ptr_src)?;
@@ -751,7 +752,7 @@ fn emulate_foreign_item_inner(
| "erff"
| "erfcf"
=> {
let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let [f] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f32()?;
// Using host floats (but it's fine, these operations do not have guaranteed precision).
let f_host = f.to_host();
@@ -789,7 +790,7 @@ fn emulate_foreign_item_inner(
| "atan2f"
| "fdimf"
=> {
let [f1, f2] = this.check_shim(abi, Conv::C , link_name, args)?;
let [f1, f2] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
let f1 = this.read_scalar(f1)?.to_f32()?;
let f2 = this.read_scalar(f2)?.to_f32()?;
// underscore case for windows, here and below
@@ -828,7 +829,7 @@ fn emulate_foreign_item_inner(
| "erf"
| "erfc"
=> {
let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let [f] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f64()?;
// Using host floats (but it's fine, these operations do not have guaranteed precision).
let f_host = f.to_host();
@@ -866,7 +867,7 @@ fn emulate_foreign_item_inner(
| "atan2"
| "fdim"
=> {
let [f1, f2] = this.check_shim(abi, Conv::C , link_name, args)?;
let [f1, f2] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
let f1 = this.read_scalar(f1)?.to_f64()?;
let f2 = this.read_scalar(f2)?.to_f64()?;
// underscore case for windows, here and below
@@ -895,7 +896,7 @@ fn emulate_foreign_item_inner(
| "ldexp"
| "scalbn"
=> {
let [x, exp] = this.check_shim(abi, Conv::C , link_name, args)?;
let [x, exp] = this.check_shim(abi, CanonAbi::C , link_name, args)?;
// For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
let x = this.read_scalar(x)?.to_f64()?;
let exp = this.read_scalar(exp)?.to_i32()?;
@@ -905,7 +906,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"lgammaf_r" => {
let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?;
let [x, signp] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let x = this.read_scalar(x)?.to_f32()?;
let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?;
@@ -921,7 +922,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"lgamma_r" => {
let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?;
let [x, signp] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let x = this.read_scalar(x)?.to_f64()?;
let signp = this.deref_pointer_as(signp, this.machine.layouts.i32)?;
@@ -939,7 +940,7 @@ fn emulate_foreign_item_inner(
// LLVM intrinsics
"llvm.prefetch" => {
let [p, rw, loc, ty] = this.check_shim(abi, Conv::C, link_name, args)?;
let [p, rw, loc, ty] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let _ = this.read_pointer(p)?;
let rw = this.read_scalar(rw)?.to_i32()?;
@@ -966,7 +967,7 @@ fn emulate_foreign_item_inner(
// Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm
// `{i,u}8x16_popcnt` functions.
name if name.starts_with("llvm.ctpop.v") => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (op, op_len) = this.project_to_simd(op)?;
let (dest, dest_len) = this.project_to_simd(dest)?;
@@ -1002,7 +1003,7 @@ fn emulate_foreign_item_inner(
}
// FIXME: Move this to an `arm` submodule.
"llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
let [arg] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let arg = this.read_scalar(arg)?.to_i32()?;
// Note that different arguments might have different target feature requirements.
match arg {
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::shims::unix::android::thread::prctl;
use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
@@ -25,29 +26,29 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// epoll, eventfd
"epoll_create1" => {
let [flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_create1(flag)?;
this.write_scalar(result, dest)?;
}
"epoll_ctl" => {
let [epfd, op, fd, event] = this.check_shim(abi, Conv::C, link_name, args)?;
let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?;
}
"epoll_wait" => {
let [epfd, events, maxevents, timeout] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
}
"eventfd" => {
let [val, flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.eventfd(val, flag)?;
this.write_scalar(result, dest)?;
}
// Miscellaneous
"__errno" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
@@ -1,7 +1,7 @@
use rustc_abi::Size;
use rustc_abi::{CanonAbi, Size};
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::helpers::check_min_vararg_count;
use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult};
@@ -16,7 +16,7 @@ pub fn prctl<'tcx>(
args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let ([op], varargs) = ecx.check_shim_variadic(abi, Conv::C, link_name, args)?;
let ([op], varargs) = ecx.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
// FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch.
let pr_set_name = 15;
+63 -61
View File
@@ -1,11 +1,11 @@
use std::ffi::OsStr;
use std::str;
use rustc_abi::{ExternAbi, Size};
use rustc_abi::{CanonAbi, ExternAbi, Size};
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use self::shims::unix::android::foreign_items as android;
use self::shims::unix::freebsd::foreign_items as freebsd;
@@ -334,7 +334,7 @@ fn emulate_foreign_item_inner(
}
"fcntl" => {
let ([fd_num, cmd], varargs) =
this.check_shim_variadic(abi, Conv::C, link_name, args)?;
this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
let result = this.fcntl(fd_num, cmd, varargs)?;
this.write_scalar(result, dest)?;
}
@@ -387,7 +387,7 @@ fn emulate_foreign_item_inner(
// `open` is variadic, the third argument is only present when the second argument
// has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set
let ([path_raw, flag], varargs) =
this.check_shim_variadic(abi, Conv::C, link_name, args)?;
this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
let result = this.open(path_raw, flag, varargs)?;
this.write_scalar(result, dest)?;
}
@@ -701,20 +701,20 @@ fn emulate_foreign_item_inner(
// Allocation
"posix_memalign" => {
let [memptr, align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [memptr, align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?;
}
"mmap" => {
let [addr, length, prot, flags, fd, offset] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
this.write_scalar(ptr, dest)?;
}
"munmap" => {
let [addr, length] = this.check_shim(abi, Conv::C, link_name, args)?;
let [addr, length] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.munmap(addr, length)?;
this.write_scalar(result, dest)?;
}
@@ -722,7 +722,7 @@ fn emulate_foreign_item_inner(
"reallocarray" => {
// Currently this function does not exist on all Unixes, e.g. on macOS.
this.check_target_os(&["linux", "freebsd", "android"], link_name)?;
let [ptr, nmemb, size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, nmemb, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let nmemb = this.read_target_usize(nmemb)?;
let size = this.read_target_usize(size)?;
@@ -745,14 +745,14 @@ fn emulate_foreign_item_inner(
"aligned_alloc" => {
// This is a C11 function, we assume all Unixes have it.
// (MSVC explicitly does not support this.)
let [align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?;
}
// Dynamic symbol loading
"dlsym" => {
let [handle, symbol] = this.check_shim(abi, Conv::C, link_name, args)?;
let [handle, symbol] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.read_target_usize(handle)?;
let symbol = this.read_pointer(symbol)?;
let name = this.read_c_str(symbol)?;
@@ -768,7 +768,7 @@ fn emulate_foreign_item_inner(
// Thread-local storage
"pthread_key_create" => {
let [key, dtor] = this.check_shim(abi, Conv::C, link_name, args)?;
let [key, dtor] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?;
let dtor = this.read_pointer(dtor)?;
@@ -796,21 +796,21 @@ fn emulate_foreign_item_inner(
this.write_null(dest)?;
}
"pthread_key_delete" => {
let [key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
this.machine.tls.delete_tls_key(key)?;
// Return success (0)
this.write_null(dest)?;
}
"pthread_getspecific" => {
let [key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
let active_thread = this.active_thread();
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
this.write_scalar(ptr, dest)?;
}
"pthread_setspecific" => {
let [key, new_ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [key, new_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
let active_thread = this.active_thread();
let new_data = this.read_scalar(new_ptr)?;
@@ -822,156 +822,157 @@ fn emulate_foreign_item_inner(
// Synchronization primitives
"pthread_mutexattr_init" => {
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_mutexattr_init(attr)?;
this.write_null(dest)?;
}
"pthread_mutexattr_settype" => {
let [attr, kind] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr, kind] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_mutexattr_settype(attr, kind)?;
this.write_scalar(result, dest)?;
}
"pthread_mutexattr_destroy" => {
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_mutexattr_destroy(attr)?;
this.write_null(dest)?;
}
"pthread_mutex_init" => {
let [mutex, attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [mutex, attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_mutex_init(mutex, attr)?;
this.write_null(dest)?;
}
"pthread_mutex_lock" => {
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_mutex_lock(mutex, dest)?;
}
"pthread_mutex_trylock" => {
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_mutex_trylock(mutex)?;
this.write_scalar(result, dest)?;
}
"pthread_mutex_unlock" => {
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_mutex_unlock(mutex)?;
this.write_scalar(result, dest)?;
}
"pthread_mutex_destroy" => {
let [mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
let [mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_mutex_destroy(mutex)?;
this.write_int(0, dest)?;
}
"pthread_rwlock_rdlock" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_rwlock_rdlock(rwlock, dest)?;
}
"pthread_rwlock_tryrdlock" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_rwlock_tryrdlock(rwlock)?;
this.write_scalar(result, dest)?;
}
"pthread_rwlock_wrlock" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_rwlock_wrlock(rwlock, dest)?;
}
"pthread_rwlock_trywrlock" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_rwlock_trywrlock(rwlock)?;
this.write_scalar(result, dest)?;
}
"pthread_rwlock_unlock" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_rwlock_unlock(rwlock)?;
this.write_null(dest)?;
}
"pthread_rwlock_destroy" => {
let [rwlock] = this.check_shim(abi, Conv::C, link_name, args)?;
let [rwlock] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_rwlock_destroy(rwlock)?;
this.write_null(dest)?;
}
"pthread_condattr_init" => {
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_condattr_init(attr)?;
this.write_null(dest)?;
}
"pthread_condattr_setclock" => {
let [attr, clock_id] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr, clock_id] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.pthread_condattr_setclock(attr, clock_id)?;
this.write_scalar(result, dest)?;
}
"pthread_condattr_getclock" => {
let [attr, clock_id] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr, clock_id] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_condattr_getclock(attr, clock_id)?;
this.write_null(dest)?;
}
"pthread_condattr_destroy" => {
let [attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_condattr_destroy(attr)?;
this.write_null(dest)?;
}
"pthread_cond_init" => {
let [cond, attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond, attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_init(cond, attr)?;
this.write_null(dest)?;
}
"pthread_cond_signal" => {
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_signal(cond)?;
this.write_null(dest)?;
}
"pthread_cond_broadcast" => {
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_broadcast(cond)?;
this.write_null(dest)?;
}
"pthread_cond_wait" => {
let [cond, mutex] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond, mutex] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_wait(cond, mutex, dest)?;
}
"pthread_cond_timedwait" => {
let [cond, mutex, abstime] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond, mutex, abstime] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_timedwait(cond, mutex, abstime, dest)?;
}
"pthread_cond_destroy" => {
let [cond] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cond] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_cond_destroy(cond)?;
this.write_null(dest)?;
}
// Threading
"pthread_create" => {
let [thread, attr, start, arg] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, attr, start, arg] =
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.pthread_create(thread, attr, start, arg)?;
this.write_null(dest)?;
}
"pthread_join" => {
let [thread, retval] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, retval] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.pthread_join(thread, retval)?;
this.write_scalar(res, dest)?;
}
"pthread_detach" => {
let [thread] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.pthread_detach(thread)?;
this.write_scalar(res, dest)?;
}
"pthread_self" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.pthread_self()?;
this.write_scalar(res, dest)?;
}
"sched_yield" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.sched_yield()?;
this.write_null(dest)?;
}
"nanosleep" => {
let [req, rem] = this.check_shim(abi, Conv::C, link_name, args)?;
let [req, rem] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.nanosleep(req, rem)?;
this.write_scalar(result, dest)?;
}
"sched_getaffinity" => {
// Currently this function does not exist on all Unixes, e.g. on macOS.
this.check_target_os(&["linux", "freebsd", "android"], link_name)?;
let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [pid, cpusetsize, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let pid = this.read_scalar(pid)?.to_u32()?;
let cpusetsize = this.read_target_usize(cpusetsize)?;
let mask = this.read_pointer(mask)?;
@@ -1008,7 +1009,7 @@ fn emulate_foreign_item_inner(
"sched_setaffinity" => {
// Currently this function does not exist on all Unixes, e.g. on macOS.
this.check_target_os(&["linux", "freebsd", "android"], link_name)?;
let [pid, cpusetsize, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [pid, cpusetsize, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let pid = this.read_scalar(pid)?.to_u32()?;
let cpusetsize = this.read_target_usize(cpusetsize)?;
let mask = this.read_pointer(mask)?;
@@ -1048,12 +1049,13 @@ fn emulate_foreign_item_inner(
// Miscellaneous
"isatty" => {
let [fd] = this.check_shim(abi, Conv::C, link_name, args)?;
let [fd] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.isatty(fd)?;
this.write_scalar(result, dest)?;
}
"pthread_atfork" => {
let [prepare, parent, child] = this.check_shim(abi, Conv::C, link_name, args)?;
let [prepare, parent, child] =
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.read_pointer(prepare)?;
this.read_pointer(parent)?;
this.read_pointer(child)?;
@@ -1067,7 +1069,7 @@ fn emulate_foreign_item_inner(
&["linux", "macos", "freebsd", "illumos", "solaris", "android"],
link_name,
)?;
let [buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?;
let [buf, bufsize] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let buf = this.read_pointer(buf)?;
let bufsize = this.read_target_usize(bufsize)?;
@@ -1085,7 +1087,7 @@ fn emulate_foreign_item_inner(
}
"strerror_r" => {
let [errnum, buf, buflen] = this.check_shim(abi, Conv::C, link_name, args)?;
let [errnum, buf, buflen] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?;
}
@@ -1097,7 +1099,7 @@ fn emulate_foreign_item_inner(
&["linux", "freebsd", "illumos", "solaris", "android"],
link_name,
)?;
let [ptr, len, flags] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, len, flags] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?;
let _flags = this.read_scalar(flags)?.to_i32()?;
@@ -1109,7 +1111,7 @@ fn emulate_foreign_item_inner(
// This function is non-standard but exists with the same signature and
// same behavior (eg never fails) on FreeBSD and Solaris/Illumos.
this.check_target_os(&["freebsd", "illumos", "solaris"], link_name)?;
let [ptr, len] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?;
this.gen_random(ptr, len)?;
@@ -1133,12 +1135,12 @@ fn emulate_foreign_item_inner(
link_name,
)?;
// This function looks and behaves excatly like miri_start_unwind.
let [payload] = this.check_shim(abi, Conv::C, link_name, args)?;
let [payload] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind);
}
"getuid" | "geteuid" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// For now, just pretend we always have this fixed UID.
this.write_int(UID, dest)?;
}
@@ -1146,7 +1148,7 @@ fn emulate_foreign_item_inner(
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"pthread_attr_getguardsize" if this.frame_in_std() => {
let [_attr, guard_size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_attr, guard_size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let guard_size_layout = this.machine.layouts.usize;
let guard_size = this.deref_pointer_as(guard_size, guard_size_layout)?;
this.write_scalar(
@@ -1159,11 +1161,11 @@ fn emulate_foreign_item_inner(
}
"pthread_attr_init" | "pthread_attr_destroy" if this.frame_in_std() => {
let [_] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
"pthread_attr_setstacksize" if this.frame_in_std() => {
let [_, _] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
@@ -1171,7 +1173,7 @@ fn emulate_foreign_item_inner(
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
// Hence we can mostly ignore the input `attr_place`.
let [attr_place, addr_place, size_place] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let _attr_place =
this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
let addr_place = this.deref_pointer_as(addr_place, this.machine.layouts.usize)?;
@@ -1191,18 +1193,18 @@ fn emulate_foreign_item_inner(
}
"signal" | "sigaltstack" if this.frame_in_std() => {
let [_, _] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
"sigaction" | "mprotect" if this.frame_in_std() => {
let [_, _, _] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_, _, _] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
"getpwuid_r" | "__posix_getpwuid_r" if this.frame_in_std() => {
// getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish
let [uid, pwd, buf, buflen, result] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.check_no_isolation("`getpwuid_r`")?;
let uid = this.read_scalar(uid)?.to_u32()?;
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::sync::EvalContextExt as _;
use crate::shims::unix::*;
@@ -23,7 +24,7 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// Threading
"pthread_setname_np" => {
let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let max_len = u64::MAX; // FreeBSD does not seem to have a limit.
let res = match this.pthread_setname_np(
this.read_scalar(thread)?,
@@ -38,7 +39,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"pthread_getname_np" => {
let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// FreeBSD's pthread_getname_np uses strlcpy, which truncates the resulting value,
// but always adds a null terminator (except for zero-sized buffers).
// https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144
@@ -59,7 +60,7 @@ fn emulate_foreign_item_inner(
"cpuset_getaffinity" => {
// The "same" kind of api as `sched_getaffinity` but more fine grained control for FreeBSD specifically.
let [level, which, id, set_size, mask] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let level = this.read_scalar(level)?.to_i32()?;
let which = this.read_scalar(which)?.to_i32()?;
@@ -123,7 +124,7 @@ fn emulate_foreign_item_inner(
// Synchronization primitives
"_umtx_op" => {
let [obj, op, val, uaddr, uaddr2] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?;
}
@@ -131,29 +132,29 @@ fn emulate_foreign_item_inner(
// For those, we both intercept `func` and `call@FBSD_1.0` symbols cases
// since freebsd 12 the former form can be expected.
"stat" | "stat@FBSD_1.0" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_stat(path, buf)?;
this.write_scalar(result, dest)?;
}
"lstat" | "lstat@FBSD_1.0" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"fstat" | "fstat@FBSD_1.0" => {
let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_fstat(fd, buf)?;
this.write_scalar(result, dest)?;
}
"readdir_r" | "readdir_r@FBSD_1.0" => {
let [dirp, entry, result] = this.check_shim(abi, Conv::C, link_name, args)?;
let [dirp, entry, result] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
this.write_scalar(result, dest)?;
}
// Miscellaneous
"__error" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
@@ -161,7 +162,7 @@ fn emulate_foreign_item_inner(
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"pthread_attr_get_np" if this.frame_in_std() => {
let [_thread, _attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_thread, _attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use self::shims::unix::linux::mem::EvalContextExt as _;
use self::shims::unix::linux_like::epoll::EvalContextExt as _;
@@ -36,47 +37,48 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// File related shims
"readdir64" => {
let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?;
let [dirp] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_solarish_readdir64("dirent64", dirp)?;
this.write_scalar(result, dest)?;
}
"sync_file_range" => {
let [fd, offset, nbytes, flags] = this.check_shim(abi, Conv::C, link_name, args)?;
let [fd, offset, nbytes, flags] =
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.sync_file_range(fd, offset, nbytes, flags)?;
this.write_scalar(result, dest)?;
}
"statx" => {
let [dirfd, pathname, flags, mask, statxbuf] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
this.write_scalar(result, dest)?;
}
// epoll, eventfd
"epoll_create1" => {
let [flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_create1(flag)?;
this.write_scalar(result, dest)?;
}
"epoll_ctl" => {
let [epfd, op, fd, event] = this.check_shim(abi, Conv::C, link_name, args)?;
let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?;
}
"epoll_wait" => {
let [epfd, events, maxevents, timeout] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
}
"eventfd" => {
let [val, flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.eventfd(val, flag)?;
this.write_scalar(result, dest)?;
}
// Threading
"pthread_setname_np" => {
let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = match this.pthread_setname_np(
this.read_scalar(thread)?,
this.read_scalar(name)?,
@@ -91,7 +93,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"pthread_getname_np" => {
let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// The function's behavior isn't portable between platforms.
// In case of glibc, the length of the output buffer must
// be not shorter than TASK_COMM_LEN.
@@ -114,7 +116,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"gettid" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_gettid()?;
this.write_scalar(result, dest)?;
}
@@ -127,34 +129,34 @@ fn emulate_foreign_item_inner(
// Miscellaneous
"mmap64" => {
let [addr, length, prot, flags, fd, offset] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let offset = this.read_scalar(offset)?.to_i64()?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?;
this.write_scalar(ptr, dest)?;
}
"mremap" => {
let ([old_address, old_size, new_size, flags], _) =
this.check_shim_variadic(abi, Conv::C, link_name, args)?;
this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
let ptr = this.mremap(old_address, old_size, new_size, flags)?;
this.write_scalar(ptr, dest)?;
}
"__xpg_strerror_r" => {
let [errnum, buf, buflen] = this.check_shim(abi, Conv::C, link_name, args)?;
let [errnum, buf, buflen] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?;
}
"__errno_location" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
"__libc_current_sigrtmin" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_int(SIGRTMIN, dest)?;
}
"__libc_current_sigrtmax" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_int(SIGRTMAX, dest)?;
}
@@ -162,7 +164,7 @@ fn emulate_foreign_item_inner(
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
// These shims are enabled only when the caller is in the standard library.
"pthread_getattr_np" if this.frame_in_std() => {
let [_thread, _attr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_thread, _attr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_null(dest)?;
}
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::helpers::check_min_vararg_count;
use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
@@ -14,7 +15,7 @@ pub fn syscall<'tcx>(
args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let ([op], varargs) = ecx.check_shim_variadic(abi, Conv::C, link_name, args)?;
let ([op], varargs) = ecx.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
// The syscall variadic function is legal to call with more arguments than needed,
// extra arguments are simply ignored. The important check is that when we use an
// argument, we have to also check all arguments *before* it to ensure that they
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::sync::{EvalContextExt as _, MacOsFutexTimeout};
use crate::shims::unix::*;
@@ -34,64 +35,64 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// errno
"__error" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
// File related shims
"close$NOCANCEL" => {
let [result] = this.check_shim(abi, Conv::C, link_name, args)?;
let [result] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.close(result)?;
this.write_scalar(result, dest)?;
}
"stat" | "stat64" | "stat$INODE64" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_stat(path, buf)?;
this.write_scalar(result, dest)?;
}
"lstat" | "lstat64" | "lstat$INODE64" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"fstat" | "fstat64" | "fstat$INODE64" => {
let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_fstat(fd, buf)?;
this.write_scalar(result, dest)?;
}
"opendir$INODE64" => {
let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
let [name] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.opendir(name)?;
this.write_scalar(result, dest)?;
}
"readdir_r" | "readdir_r$INODE64" => {
let [dirp, entry, result] = this.check_shim(abi, Conv::C, link_name, args)?;
let [dirp, entry, result] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
this.write_scalar(result, dest)?;
}
"realpath$DARWIN_EXTSN" => {
let [path, resolved_path] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, resolved_path] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.realpath(path, resolved_path)?;
this.write_scalar(result, dest)?;
}
"ioctl" => {
let ([fd_num, cmd], varargs) =
this.check_shim_variadic(abi, Conv::C, link_name, args)?;
this.check_shim_variadic(abi, CanonAbi::C, link_name, args)?;
let result = this.ioctl(fd_num, cmd, varargs)?;
this.write_scalar(result, dest)?;
}
// Environment related shims
"_NSGetEnviron" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let environ = this.machine.env_vars.unix().environ();
this.write_pointer(environ, dest)?;
}
// Random data generation
"CCRandomGenerateBytes" => {
let [bytes, count] = this.check_shim(abi, Conv::C, link_name, args)?;
let [bytes, count] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let bytes = this.read_pointer(bytes)?;
let count = this.read_target_usize(count)?;
let success = this.eval_libc_i32("kCCSuccess");
@@ -101,28 +102,28 @@ fn emulate_foreign_item_inner(
// Time related shims
"mach_absolute_time" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.mach_absolute_time()?;
this.write_scalar(result, dest)?;
}
"mach_timebase_info" => {
let [info] = this.check_shim(abi, Conv::C, link_name, args)?;
let [info] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.mach_timebase_info(info)?;
this.write_scalar(result, dest)?;
}
// Access to command-line arguments
"_NSGetArgc" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_pointer(this.machine.argc.expect("machine must be initialized"), dest)?;
}
"_NSGetArgv" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.write_pointer(this.machine.argv.expect("machine must be initialized"), dest)?;
}
"_NSGetExecutablePath" => {
let [buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?;
let [buf, bufsize] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.check_no_isolation("`_NSGetExecutablePath`")?;
let buf_ptr = this.read_pointer(buf)?;
@@ -147,7 +148,7 @@ fn emulate_foreign_item_inner(
// Thread-local storage
"_tlv_atexit" => {
let [dtor, data] = this.check_shim(abi, Conv::C, link_name, args)?;
let [dtor, data] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let dtor = this.read_pointer(dtor)?;
let dtor = this.get_ptr_fn(dtor)?.as_instance()?;
let data = this.read_scalar(data)?;
@@ -157,13 +158,13 @@ fn emulate_foreign_item_inner(
// Querying system information
"pthread_get_stackaddr_np" => {
let [thread] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.read_target_usize(thread)?;
let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size());
this.write_scalar(stack_addr, dest)?;
}
"pthread_get_stacksize_np" => {
let [thread] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.read_target_usize(thread)?;
let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size());
this.write_scalar(stack_size, dest)?;
@@ -171,7 +172,7 @@ fn emulate_foreign_item_inner(
// Threading
"pthread_setname_np" => {
let [name] = this.check_shim(abi, Conv::C, link_name, args)?;
let [name] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// The real implementation has logic in two places:
// * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200,
@@ -198,7 +199,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"pthread_getname_np" => {
let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// The function's behavior isn't portable between platforms.
// In case of macOS, a truncated name (due to a too small buffer)
@@ -225,7 +226,7 @@ fn emulate_foreign_item_inner(
// Synchronization primitives
"os_sync_wait_on_address" => {
let [addr_op, value_op, size_op, flags_op] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_sync_wait_on_address(
addr_op,
value_op,
@@ -237,7 +238,7 @@ fn emulate_foreign_item_inner(
}
"os_sync_wait_on_address_with_deadline" => {
let [addr_op, value_op, size_op, flags_op, clock_op, timeout_op] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_sync_wait_on_address(
addr_op,
value_op,
@@ -249,7 +250,7 @@ fn emulate_foreign_item_inner(
}
"os_sync_wait_on_address_with_timeout" => {
let [addr_op, value_op, size_op, flags_op, clock_op, timeout_op] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_sync_wait_on_address(
addr_op,
value_op,
@@ -261,36 +262,36 @@ fn emulate_foreign_item_inner(
}
"os_sync_wake_by_address_any" => {
let [addr_op, size_op, flags_op] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_sync_wake_by_address(
addr_op, size_op, flags_op, /* all */ false, dest,
)?;
}
"os_sync_wake_by_address_all" => {
let [addr_op, size_op, flags_op] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_sync_wake_by_address(
addr_op, size_op, flags_op, /* all */ true, dest,
)?;
}
"os_unfair_lock_lock" => {
let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_unfair_lock_lock(lock_op)?;
}
"os_unfair_lock_trylock" => {
let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_unfair_lock_trylock(lock_op, dest)?;
}
"os_unfair_lock_unlock" => {
let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_unfair_lock_unlock(lock_op)?;
}
"os_unfair_lock_assert_owner" => {
let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_unfair_lock_assert_owner(lock_op)?;
}
"os_unfair_lock_assert_not_owner" => {
let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [lock_op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.os_unfair_lock_assert_not_owner(lock_op)?;
}
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::shims::unix::foreign_items::EvalContextExt as _;
use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
@@ -26,32 +27,32 @@ fn emulate_foreign_item_inner(
// epoll, eventfd (NOT available on Solaris!)
"epoll_create1" => {
this.assert_target_os("illumos", "epoll_create1");
let [flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_create1(flag)?;
this.write_scalar(result, dest)?;
}
"epoll_ctl" => {
this.assert_target_os("illumos", "epoll_ctl");
let [epfd, op, fd, event] = this.check_shim(abi, Conv::C, link_name, args)?;
let [epfd, op, fd, event] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?;
}
"epoll_wait" => {
this.assert_target_os("illumos", "epoll_wait");
let [epfd, events, maxevents, timeout] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
}
"eventfd" => {
this.assert_target_os("illumos", "eventfd");
let [val, flag] = this.check_shim(abi, Conv::C, link_name, args)?;
let [val, flag] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.eventfd(val, flag)?;
this.write_scalar(result, dest)?;
}
// Threading
"pthread_setname_np" => {
let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// THREAD_NAME_MAX allows a thread name of 31+1 length
// https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613
let max_len = 32;
@@ -69,7 +70,7 @@ fn emulate_foreign_item_inner(
this.write_scalar(res, dest)?;
}
"pthread_getname_np" => {
let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?;
let [thread, name, len] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// See https://illumos.org/man/3C/pthread_getname_np for the error codes.
let res = match this.pthread_getname_np(
this.read_scalar(thread)?,
@@ -86,22 +87,22 @@ fn emulate_foreign_item_inner(
// File related shims
"stat" | "stat64" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_stat(path, buf)?;
this.write_scalar(result, dest)?;
}
"lstat" | "lstat64" => {
let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [path, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_lstat(path, buf)?;
this.write_scalar(result, dest)?;
}
"fstat" | "fstat64" => {
let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
let [fd, buf] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.macos_fbsd_solarish_fstat(fd, buf)?;
this.write_scalar(result, dest)?;
}
"readdir" => {
let [dirp] = this.check_shim(abi, Conv::C, link_name, args)?;
let [dirp] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.linux_solarish_readdir64("dirent", dirp)?;
this.write_scalar(result, dest)?;
}
@@ -109,20 +110,20 @@ fn emulate_foreign_item_inner(
// Sockets and pipes
"__xnet_socketpair" => {
let [domain, type_, protocol, sv] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.socketpair(domain, type_, protocol, sv)?;
this.write_scalar(result, dest)?;
}
// Miscellaneous
"___errno" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
}
"stack_getbounds" => {
let [stack] = this.check_shim(abi, Conv::C, link_name, args)?;
let [stack] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?;
this.write_int_fields_named(
@@ -140,7 +141,7 @@ fn emulate_foreign_item_inner(
}
"pset_info" => {
let [pset, tpe, cpus, list] = this.check_shim(abi, Conv::C, link_name, args)?;
let [pset, tpe, cpus, list] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// We do not need to handle the current process cpu mask, available_parallelism
// implementation pass null anyway. We only care for the number of
// cpus.
@@ -169,7 +170,7 @@ fn emulate_foreign_item_inner(
}
"__sysconf_xpg7" => {
let [val] = this.check_shim(abi, Conv::C, link_name, args)?;
let [val] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.sysconf(val)?;
this.write_scalar(result, dest)?;
}
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::shims::alloc::EvalContextExt as _;
use crate::*;
@@ -22,12 +23,12 @@ fn emulate_foreign_item_inner(
match link_name.as_str() {
// Allocation
"posix_memalign" => {
let [memptr, align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [memptr, align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?;
}
"aligned_alloc" => {
let [align, size] = this.check_shim(abi, Conv::C, link_name, args)?;
let [align, size] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?;
}
@@ -2,10 +2,10 @@
use std::path::{self, Path, PathBuf};
use std::{io, iter, str};
use rustc_abi::{Align, Size};
use rustc_abi::{Align, CanonAbi, Size, X86Call};
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use self::shims::windows::handle::{Handle, PseudoHandle};
use crate::shims::os_str::bytes_to_os_str;
@@ -140,7 +140,11 @@ fn emulate_foreign_item_inner(
// https://github.com/rust-lang/rust/blob/fb00adbdb69266f10df95a4527b767b0ad35ea48/compiler/rustc_target/src/spec/mod.rs#L2766-L2768,
// x86-32 Windows uses a different calling convention than other Windows targets
// for the "system" ABI.
let sys_conv = if this.tcx.sess.target.arch == "x86" { Conv::X86Stdcall } else { Conv::C };
let sys_conv = if this.tcx.sess.target.arch == "x86" {
CanonAbi::X86(X86Call::Stdcall)
} else {
CanonAbi::C
};
// See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
@@ -856,7 +860,7 @@ fn emulate_foreign_item_inner(
);
}
// This function looks and behaves excatly like miri_start_unwind.
let [payload] = this.check_shim(abi, Conv::C, link_name, args)?;
let [payload] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind);
}
+7 -6
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -26,7 +27,7 @@ fn emulate_x86_aesni_intrinsic(
// `state` with the corresponding 128-bit key of `key`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128
"aesdec" | "aesdec.256" | "aesdec.512" => {
let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| {
let key = aes::Block::from(key.to_le_bytes());
let mut state = aes::Block::from(state.to_le_bytes());
@@ -42,7 +43,7 @@ fn emulate_x86_aesni_intrinsic(
// `state` with the corresponding 128-bit key of `key`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128
"aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => {
let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| {
let mut state = aes::Block::from(state.to_le_bytes());
@@ -66,7 +67,7 @@ fn emulate_x86_aesni_intrinsic(
// `state` with the corresponding 128-bit key of `key`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128
"aesenc" | "aesenc.256" | "aesenc.512" => {
let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| {
let key = aes::Block::from(key.to_le_bytes());
let mut state = aes::Block::from(state.to_le_bytes());
@@ -82,7 +83,7 @@ fn emulate_x86_aesni_intrinsic(
// `state` with the corresponding 128-bit key of `key`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128
"aesenclast" | "aesenclast.256" | "aesenclast.512" => {
let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?;
let [state, key] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| {
let mut state = aes::Block::from(state.to_le_bytes());
// `aes::hazmat::cipher_round` does the following operations:
@@ -102,7 +103,7 @@ fn emulate_x86_aesni_intrinsic(
// Used to implement the _mm_aesimc_si128 function.
// Performs the AES InvMixColumns operation on `op`
"aesimc" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// Transmute to `u128`
let op = op.transmute(this.machine.layouts.u128, this)?;
let dest = dest.transmute(this.machine.layouts.u128, this)?;
+21 -20
View File
@@ -1,9 +1,10 @@
use rustc_abi::CanonAbi;
use rustc_apfloat::ieee::{Double, Single};
use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{
FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, conditional_dot_product, convert_float_to_int,
@@ -33,7 +34,7 @@ fn emulate_x86_avx_intrinsic(
// matches the IEEE min/max operations, while x86 has different
// semantics.
"min.ps.256" | "max.ps.256" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.ps.256" => FloatBinOp::Min,
@@ -45,7 +46,7 @@ fn emulate_x86_avx_intrinsic(
}
// Used to implement _mm256_min_pd and _mm256_max_pd functions.
"min.pd.256" | "max.pd.256" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.pd.256" => FloatBinOp::Min,
@@ -58,21 +59,21 @@ fn emulate_x86_avx_intrinsic(
// Used to implement the _mm256_round_ps function.
// Rounds the elements of `op` according to `rounding`.
"round.ps.256" => {
let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?;
}
// Used to implement the _mm256_round_pd function.
// Rounds the elements of `op` according to `rounding`.
"round.pd.256" => {
let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?;
}
// Used to implement _mm256_{rcp,rsqrt}_ps functions.
// Performs the operations on all components of `op`.
"rcp.ps.256" | "rsqrt.ps.256" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"rcp.ps.256" => FloatUnaryOp::Rcp,
@@ -84,7 +85,7 @@ fn emulate_x86_avx_intrinsic(
}
// Used to implement the _mm256_dp_ps function.
"dp.ps.256" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
conditional_dot_product(this, left, right, imm, dest)?;
}
@@ -92,7 +93,7 @@ fn emulate_x86_avx_intrinsic(
// Horizontally add/subtract adjacent floating point values
// in `left` and `right`.
"hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add,
@@ -107,7 +108,7 @@ fn emulate_x86_avx_intrinsic(
// and `right`. For each component, returns 0 if false or u32::MAX
// if true.
"cmp.ps.256" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -119,7 +120,7 @@ fn emulate_x86_avx_intrinsic(
// and `right`. For each component, returns 0 if false or u64::MAX
// if true.
"cmp.pd.256" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -130,7 +131,7 @@ fn emulate_x86_avx_intrinsic(
// and _mm256_cvttpd_epi32 functions.
// Converts packed f32/f64 to packed i32.
"cvt.ps2dq.256" | "cvtt.ps2dq.256" | "cvt.pd2dq.256" | "cvtt.pd2dq.256" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let rnd = match unprefixed_name {
// "current SSE rounding mode", assume nearest
@@ -148,7 +149,7 @@ fn emulate_x86_avx_intrinsic(
// sequence of 4-element arrays, and we shuffle each of these arrays, where
// `control` determines which element of the current `data` array is written.
"vpermilvar.ps" | "vpermilvar.ps.256" => {
let [data, control] = this.check_shim(abi, Conv::C, link_name, args)?;
let [data, control] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (data, data_len) = this.project_to_simd(data)?;
let (control, control_len) = this.project_to_simd(control)?;
@@ -181,7 +182,7 @@ fn emulate_x86_avx_intrinsic(
// where `right` determines which element of the current `left` array is
// written.
"vpermilvar.pd" | "vpermilvar.pd.256" => {
let [data, control] = this.check_shim(abi, Conv::C, link_name, args)?;
let [data, control] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (data, data_len) = this.project_to_simd(data)?;
let (control, control_len) = this.project_to_simd(control)?;
@@ -213,7 +214,7 @@ fn emulate_x86_avx_intrinsic(
// For each 128-bit element of `dest`, copies one from `left`, `right` or
// zero, according to `imm`.
"vperm2f128.ps.256" | "vperm2f128.pd.256" | "vperm2f128.si.256" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
assert_eq!(dest.layout, left.layout);
assert_eq!(dest.layout, right.layout);
@@ -256,7 +257,7 @@ fn emulate_x86_avx_intrinsic(
// is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is
// loaded.
"maskload.ps" | "maskload.pd" | "maskload.ps.256" | "maskload.pd.256" => {
let [ptr, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mask_load(this, ptr, mask, dest)?;
}
@@ -266,7 +267,7 @@ fn emulate_x86_avx_intrinsic(
// is one, it is stored into `ptr.wapping_add(i)`.
// Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores.
"maskstore.ps" | "maskstore.pd" | "maskstore.ps.256" | "maskstore.pd.256" => {
let [ptr, mask, value] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, mask, value] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mask_store(this, ptr, mask, value)?;
}
@@ -276,7 +277,7 @@ fn emulate_x86_avx_intrinsic(
// the data crosses a cache line, but for Miri this is just a regular
// unaligned read.
"ldu.dq.256" => {
let [src_ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [src_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let src_ptr = this.read_pointer(src_ptr)?;
let dest = dest.force_mplace(this)?;
@@ -288,7 +289,7 @@ fn emulate_x86_avx_intrinsic(
// Tests `op & mask == 0`, `op & mask == mask` or
// `op & mask != 0 && op & mask != mask`
"ptestz.256" | "ptestc.256" | "ptestnzc.256" => {
let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
let res = match unprefixed_name {
@@ -311,7 +312,7 @@ fn emulate_x86_avx_intrinsic(
"vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestz.pd" | "vtestc.pd"
| "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256"
| "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => {
let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (direct, negated) = test_high_bits_masked(this, op, mask)?;
let res = match unprefixed_name {
@@ -333,7 +334,7 @@ fn emulate_x86_avx_intrinsic(
// compiler, making these functions no-ops.
// The only thing that needs to be ensured is the correct calling convention.
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
}
_ => return interp_ok(EmulateItemResult::NotSupported),
}
+22 -21
View File
@@ -1,8 +1,9 @@
use rustc_abi::CanonAbi;
use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{
ShiftOp, horizontal_bin_op, int_abs, mask_load, mask_store, mpsadbw, packssdw, packsswb,
@@ -28,7 +29,7 @@ fn emulate_x86_avx2_intrinsic(
// Used to implement the _mm256_abs_epi{8,16,32} functions.
// Calculates the absolute value of packed 8/16/32-bit integers.
"pabs.b" | "pabs.w" | "pabs.d" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
int_abs(this, op, dest)?;
}
@@ -36,7 +37,7 @@ fn emulate_x86_avx2_intrinsic(
// Horizontally add / add with saturation / subtract adjacent 16/32-bit
// integer values in `left` and `right`.
"phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (which, saturating) = match unprefixed_name {
"phadd.w" | "phadd.d" => (mir::BinOp::Add, false),
@@ -57,7 +58,7 @@ fn emulate_x86_avx2_intrinsic(
| "gather.d.pd.256" | "gather.q.pd" | "gather.q.pd.256" | "gather.d.ps"
| "gather.d.ps.256" | "gather.q.ps" | "gather.q.ps.256" => {
let [src, slice, offsets, mask, scale] =
this.check_shim(abi, Conv::C, link_name, args)?;
this.check_shim(abi, CanonAbi::C, link_name, args)?;
assert_eq!(dest.layout, src.layout);
@@ -114,7 +115,7 @@ fn emulate_x86_avx2_intrinsic(
// intermediate signed 32-bit integers. Horizontally add adjacent pairs of
// intermediate 32-bit integers, and pack the results in `dest`.
"pmadd.wd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -150,7 +151,7 @@ fn emulate_x86_avx2_intrinsic(
// the saturating sum of the products with indices `2*i` and `2*i+1`
// produces the output at index `i`.
"pmadd.ub.sw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -184,7 +185,7 @@ fn emulate_x86_avx2_intrinsic(
// is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is
// loaded.
"maskload.d" | "maskload.q" | "maskload.d.256" | "maskload.q.256" => {
let [ptr, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mask_load(this, ptr, mask, dest)?;
}
@@ -194,7 +195,7 @@ fn emulate_x86_avx2_intrinsic(
// is one, it is stored into `ptr.wapping_add(i)`.
// Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores.
"maskstore.d" | "maskstore.q" | "maskstore.d.256" | "maskstore.q.256" => {
let [ptr, mask, value] = this.check_shim(abi, Conv::C, link_name, args)?;
let [ptr, mask, value] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mask_store(this, ptr, mask, value)?;
}
@@ -205,7 +206,7 @@ fn emulate_x86_avx2_intrinsic(
// offsets specified in `imm`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mpsadbw_epu8
"mpsadbw" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mpsadbw(this, left, right, imm, dest)?;
}
@@ -216,7 +217,7 @@ fn emulate_x86_avx2_intrinsic(
// 1 and then taking the bits `1..=16`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16
"pmul.hr.sw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
pmulhrsw(this, left, right, dest)?;
}
@@ -224,7 +225,7 @@ fn emulate_x86_avx2_intrinsic(
// Converts two 16-bit integer vectors to a single 8-bit integer
// vector with signed saturation.
"packsswb" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packsswb(this, left, right, dest)?;
}
@@ -232,7 +233,7 @@ fn emulate_x86_avx2_intrinsic(
// Converts two 32-bit integer vectors to a single 16-bit integer
// vector with signed saturation.
"packssdw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packssdw(this, left, right, dest)?;
}
@@ -240,7 +241,7 @@ fn emulate_x86_avx2_intrinsic(
// Converts two 16-bit signed integer vectors to a single 8-bit
// unsigned integer vector with saturation.
"packuswb" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packuswb(this, left, right, dest)?;
}
@@ -248,7 +249,7 @@ fn emulate_x86_avx2_intrinsic(
// Concatenates two 32-bit signed integer vectors and converts
// the result to a 16-bit unsigned integer vector with saturation.
"packusdw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packusdw(this, left, right, dest)?;
}
@@ -257,7 +258,7 @@ fn emulate_x86_avx2_intrinsic(
// Shuffles `left` using the three low bits of each element of `right`
// as indices.
"permd" | "permps" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -277,7 +278,7 @@ fn emulate_x86_avx2_intrinsic(
// Used to implement the _mm256_permute2x128_si256 function.
// Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern.
"vperm2i128" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
assert_eq!(left.layout.size.bits(), 256);
assert_eq!(right.layout.size.bits(), 256);
@@ -314,7 +315,7 @@ fn emulate_x86_avx2_intrinsic(
// in `dest`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8
"psad.bw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -346,7 +347,7 @@ fn emulate_x86_avx2_intrinsic(
// Shuffles bytes from `left` using `right` as pattern.
// Each 128-bit block is shuffled independently.
"pshuf.b" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -377,7 +378,7 @@ fn emulate_x86_avx2_intrinsic(
// is writen to the corresponding output element.
// Basically, we multiply `left` with `right.signum()`.
"psign.b" | "psign.w" | "psign.d" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
psign(this, left, right, dest)?;
}
@@ -391,7 +392,7 @@ fn emulate_x86_avx2_intrinsic(
// is copied to remaining bits.
"psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q"
| "psrl.q" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"psll.w" | "psll.d" | "psll.q" => ShiftOp::Left,
@@ -406,7 +407,7 @@ fn emulate_x86_avx2_intrinsic(
// (except _mm{,256}_srav_epi64, which are not available in AVX2).
"psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" | "psrlv.d" | "psrlv.d.256"
| "psrlv.q" | "psrlv.q.256" | "psrav.d" | "psrav.d.256" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" => ShiftOp::Left,
+3 -2
View File
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -34,7 +35,7 @@ fn emulate_x86_bmi_intrinsic(
return interp_ok(EmulateItemResult::NotSupported);
}
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let left = this.read_scalar(left)?;
let right = this.read_scalar(right)?;
+5 -4
View File
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -30,14 +31,14 @@ fn emulate_x86_gfni_intrinsic(
// See `affine_transform` for details.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affine_
"vgf2p8affineqb.128" | "vgf2p8affineqb.256" | "vgf2p8affineqb.512" => {
let [left, right, imm8] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm8] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
affine_transform(this, left, right, imm8, dest, /* inverse */ false)?;
}
// Used to implement the `_mm{, 256, 512}_gf2p8affineinv_epi64_epi8` functions.
// See `affine_transform` for details.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affineinv
"vgf2p8affineinvqb.128" | "vgf2p8affineinvqb.256" | "vgf2p8affineinvqb.512" => {
let [left, right, imm8] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm8] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
affine_transform(this, left, right, imm8, dest, /* inverse */ true)?;
}
// Used to implement the `_mm{, 256, 512}_gf2p8mul_epi8` functions.
@@ -46,7 +47,7 @@ fn emulate_x86_gfni_intrinsic(
// polynomial representation with the reduction polynomial x^8 + x^4 + x^3 + x + 1.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8mul
"vgf2p8mulb.128" | "vgf2p8mulb.256" | "vgf2p8mulb.512" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
let (dest, dest_len) = this.project_to_simd(dest)?;
+6 -6
View File
@@ -1,11 +1,11 @@
use rustc_abi::Size;
use rustc_abi::{CanonAbi, Size};
use rustc_apfloat::Float;
use rustc_apfloat::ieee::Single;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_middle::{mir, ty};
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use self::helpers::bool_to_simd_element;
use crate::*;
@@ -46,7 +46,7 @@ fn emulate_x86_intrinsic(
return interp_ok(EmulateItemResult::NotSupported);
}
let [cb_in, a, b] = this.check_shim(abi, Conv::C, link_name, args)?;
let [cb_in, a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let op = if unprefixed_name.starts_with("add") {
mir::BinOp::AddWithOverflow
} else {
@@ -68,7 +68,7 @@ fn emulate_x86_intrinsic(
if is_u64 && this.tcx.sess.target.arch != "x86_64" {
return interp_ok(EmulateItemResult::NotSupported);
}
let [c_in, a, b, out] = this.check_shim(abi, Conv::C, link_name, args)?;
let [c_in, a, b, out] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let out = this.deref_pointer_as(
out,
if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 },
@@ -85,7 +85,7 @@ fn emulate_x86_intrinsic(
// the instruction behaves like a no-op, so it is always safe to call the
// intrinsic.
"sse2.pause" => {
let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let [] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
// Only exhibit the spin-loop hint behavior when SSE2 is enabled.
if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) {
this.yield_active_thread();
@@ -104,7 +104,7 @@ fn emulate_x86_intrinsic(
len = 8;
}
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
pclmulqdq(this, left, right, imm, dest, len)?;
}
+5 -4
View File
@@ -4,9 +4,10 @@
//!
//! [RustCrypto's sha256 module]: https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/soft.rs
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -52,7 +53,7 @@ fn write<'c>(
match unprefixed_name {
// Used to implement the _mm_sha256rnds2_epu32 function.
"256rnds2" => {
let [a, b, k] = this.check_shim(abi, Conv::C, link_name, args)?;
let [a, b, k] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?;
@@ -73,7 +74,7 @@ fn write<'c>(
}
// Used to implement the _mm_sha256msg1_epu32 function.
"256msg1" => {
let [a, b] = this.check_shim(abi, Conv::C, link_name, args)?;
let [a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?;
@@ -91,7 +92,7 @@ fn write<'c>(
}
// Used to implement the _mm_sha256msg2_epu32 function.
"256msg2" => {
let [a, b] = this.check_shim(abi, Conv::C, link_name, args)?;
let [a, b] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?;
+11 -10
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_apfloat::ieee::Single;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{
FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, bin_op_simd_float_first, unary_op_ps,
@@ -33,7 +34,7 @@ fn emulate_x86_sse_intrinsic(
// Performs the operations on the first component of `left` and
// `right` and copies the remaining components from `left`.
"min.ss" | "max.ss" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.ss" => FloatBinOp::Min,
@@ -49,7 +50,7 @@ fn emulate_x86_sse_intrinsic(
// matches the IEEE min/max operations, while x86 has different
// semantics.
"min.ps" | "max.ps" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.ps" => FloatBinOp::Min,
@@ -63,7 +64,7 @@ fn emulate_x86_sse_intrinsic(
// Performs the operations on the first component of `op` and
// copies the remaining components from `op`.
"rcp.ss" | "rsqrt.ss" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"rcp.ss" => FloatUnaryOp::Rcp,
@@ -76,7 +77,7 @@ fn emulate_x86_sse_intrinsic(
// Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions.
// Performs the operations on all components of `op`.
"rcp.ps" | "rsqrt.ps" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"rcp.ps" => FloatUnaryOp::Rcp,
@@ -95,7 +96,7 @@ fn emulate_x86_sse_intrinsic(
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions
// with hard-coded operations.
"cmp.ss" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -111,7 +112,7 @@ fn emulate_x86_sse_intrinsic(
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions
// with hard-coded operations.
"cmp.ps" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -124,7 +125,7 @@ fn emulate_x86_sse_intrinsic(
"comieq.ss" | "comilt.ss" | "comile.ss" | "comigt.ss" | "comige.ss" | "comineq.ss"
| "ucomieq.ss" | "ucomilt.ss" | "ucomile.ss" | "ucomigt.ss" | "ucomige.ss"
| "ucomineq.ss" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -152,7 +153,7 @@ fn emulate_x86_sse_intrinsic(
// _mm_cvtss_si64 and _mm_cvttss_si64 functions.
// Converts the first component of `op` from f32 to i32/i64.
"cvtss2si" | "cvttss2si" | "cvtss2si64" | "cvttss2si64" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (op, _) = this.project_to_simd(op)?;
let op = this.read_immediate(&this.project_index(&op, 0)?)?;
@@ -180,7 +181,7 @@ fn emulate_x86_sse_intrinsic(
// are copied from `left`.
// https://www.felixcloutier.com/x86/cvtsi2ss
"cvtsi2ss" | "cvtsi642ss" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (dest, dest_len) = this.project_to_simd(dest)?;
+16 -15
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_apfloat::ieee::Double;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{
FloatBinOp, ShiftOp, bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int,
@@ -40,7 +41,7 @@ fn emulate_x86_sse2_intrinsic(
// intermediate signed 32-bit integers. Horizontally add adjacent pairs of
// intermediate 32-bit integers, and pack the results in `dest`.
"pmadd.wd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -78,7 +79,7 @@ fn emulate_x86_sse2_intrinsic(
//
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8
"psad.bw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -116,7 +117,7 @@ fn emulate_x86_sse2_intrinsic(
// is copied to remaining bits.
"psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q"
| "psrl.q" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"psll.w" | "psll.d" | "psll.q" => ShiftOp::Left,
@@ -131,7 +132,7 @@ fn emulate_x86_sse2_intrinsic(
// and _mm_cvttpd_epi32 functions.
// Converts packed f32/f64 to packed i32.
"cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx);
let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx);
@@ -168,7 +169,7 @@ fn emulate_x86_sse2_intrinsic(
// Converts two 16-bit integer vectors to a single 8-bit integer
// vector with signed saturation.
"packsswb.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packsswb(this, left, right, dest)?;
}
@@ -176,7 +177,7 @@ fn emulate_x86_sse2_intrinsic(
// Converts two 16-bit signed integer vectors to a single 8-bit
// unsigned integer vector with saturation.
"packuswb.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packuswb(this, left, right, dest)?;
}
@@ -184,7 +185,7 @@ fn emulate_x86_sse2_intrinsic(
// Converts two 32-bit integer vectors to a single 16-bit integer
// vector with signed saturation.
"packssdw.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packssdw(this, left, right, dest)?;
}
@@ -194,7 +195,7 @@ fn emulate_x86_sse2_intrinsic(
// matches the IEEE min/max operations, while x86 has different
// semantics.
"min.sd" | "max.sd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.sd" => FloatBinOp::Min,
@@ -210,7 +211,7 @@ fn emulate_x86_sse2_intrinsic(
// matches the IEEE min/max operations, while x86 has different
// semantics.
"min.pd" | "max.pd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"min.pd" => FloatBinOp::Min,
@@ -229,7 +230,7 @@ fn emulate_x86_sse2_intrinsic(
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions
// with hard-coded operations.
"cmp.sd" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -245,7 +246,7 @@ fn emulate_x86_sse2_intrinsic(
// _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions
// with hard-coded operations.
"cmp.pd" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@@ -258,7 +259,7 @@ fn emulate_x86_sse2_intrinsic(
"comieq.sd" | "comilt.sd" | "comile.sd" | "comigt.sd" | "comige.sd" | "comineq.sd"
| "ucomieq.sd" | "ucomilt.sd" | "ucomile.sd" | "ucomigt.sd" | "ucomige.sd"
| "ucomineq.sd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -286,7 +287,7 @@ fn emulate_x86_sse2_intrinsic(
// _mm_cvtsd_si64 and _mm_cvttsd_si64 functions.
// Converts the first component of `op` from f64 to i32/i64.
"cvtsd2si" | "cvttsd2si" | "cvtsd2si64" | "cvttsd2si64" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (op, _) = this.project_to_simd(op)?;
let op = this.read_immediate(&this.project_index(&op, 0)?)?;
@@ -312,7 +313,7 @@ fn emulate_x86_sse2_intrinsic(
// Converts the first f64/f32 from `right` to f32/f64 and copies
// the remaining elements from `left`
"cvtsd2ss" | "cvtss2sd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, _) = this.project_to_simd(right)?;
+4 -3
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::horizontal_bin_op;
use crate::*;
@@ -25,7 +26,7 @@ fn emulate_x86_sse3_intrinsic(
// Horizontally add/subtract adjacent floating point values
// in `left` and `right`.
"hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let which = match unprefixed_name {
"hadd.ps" | "hadd.pd" => mir::BinOp::Add,
@@ -41,7 +42,7 @@ fn emulate_x86_sse3_intrinsic(
// the data crosses a cache line, but for Miri this is just a regular
// unaligned read.
"ldu.dq" => {
let [src_ptr] = this.check_shim(abi, Conv::C, link_name, args)?;
let [src_ptr] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let src_ptr = this.read_pointer(src_ptr)?;
let dest = dest.force_mplace(this)?;
+12 -11
View File
@@ -1,6 +1,7 @@
use rustc_abi::CanonAbi;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked};
use crate::*;
@@ -27,7 +28,7 @@ fn emulate_x86_sse41_intrinsic(
// bits `4..=5` if `imm`, and `i`th bit specifies whether element
// `i` is zeroed.
"insertps" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -62,7 +63,7 @@ fn emulate_x86_sse41_intrinsic(
// Concatenates two 32-bit signed integer vectors and converts
// the result to a 16-bit unsigned integer vector with saturation.
"packusdw" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
packusdw(this, left, right, dest)?;
}
@@ -72,7 +73,7 @@ fn emulate_x86_sse41_intrinsic(
// products, and conditionally stores the sum in `dest` using the low
// 4 bits of `imm`.
"dpps" | "dppd" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
conditional_dot_product(this, left, right, imm, dest)?;
}
@@ -80,14 +81,14 @@ fn emulate_x86_sse41_intrinsic(
// functions. Rounds the first element of `right` according to `rounding`
// and copies the remaining elements from `left`.
"round.ss" => {
let [left, right, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_first::<rustc_apfloat::ieee::Single>(this, left, right, rounding, dest)?;
}
// Used to implement the _mm_floor_ps, _mm_ceil_ps and _mm_round_ps
// functions. Rounds the elements of `op` according to `rounding`.
"round.ps" => {
let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?;
}
@@ -95,14 +96,14 @@ fn emulate_x86_sse41_intrinsic(
// functions. Rounds the first element of `right` according to `rounding`
// and copies the remaining elements from `left`.
"round.sd" => {
let [left, right, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_first::<rustc_apfloat::ieee::Double>(this, left, right, rounding, dest)?;
}
// Used to implement the _mm_floor_pd, _mm_ceil_pd and _mm_round_pd
// functions. Rounds the elements of `op` according to `rounding`.
"round.pd" => {
let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, rounding] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?;
}
@@ -110,7 +111,7 @@ fn emulate_x86_sse41_intrinsic(
// Find the minimum unsinged 16-bit integer in `op` and
// returns its value and position.
"phminposuw" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (op, op_len) = this.project_to_simd(op)?;
let (dest, dest_len) = this.project_to_simd(dest)?;
@@ -144,7 +145,7 @@ fn emulate_x86_sse41_intrinsic(
// offsets specified in `imm`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8
"mpsadbw" => {
let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
mpsadbw(this, left, right, imm, dest)?;
}
@@ -153,7 +154,7 @@ fn emulate_x86_sse41_intrinsic(
// Tests `(op & mask) == 0`, `(op & mask) == mask` or
// `(op & mask) != 0 && (op & mask) != mask`
"ptestz" | "ptestc" | "ptestnzc" => {
let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op, mask] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
let res = match unprefixed_name {
+7 -7
View File
@@ -1,9 +1,9 @@
use rustc_abi::Size;
use rustc_abi::{CanonAbi, Size};
use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use crate::*;
@@ -223,7 +223,7 @@ fn deconstruct_args<'tcx>(
};
if is_explicit {
let [str1, len1, str2, len2, imm] = ecx.check_shim(abi, Conv::C, link_name, args)?;
let [str1, len1, str2, len2, imm] = ecx.check_shim(abi, CanonAbi::C, link_name, args)?;
let imm = ecx.read_scalar(imm)?.to_u8()?;
let default_len = default_len::<u32>(imm);
@@ -236,7 +236,7 @@ fn deconstruct_args<'tcx>(
interp_ok((str1, str2, Some((len1, len2)), imm))
} else {
let [str1, str2, imm] = ecx.check_shim(abi, Conv::C, link_name, args)?;
let [str1, str2, imm] = ecx.check_shim(abi, CanonAbi::C, link_name, args)?;
let imm = ecx.read_scalar(imm)?.to_u8()?;
let array_layout = array_layout_fn(ecx, imm)?;
@@ -386,7 +386,7 @@ fn emulate_x86_sse42_intrinsic(
// search for a null terminator (see `deconstruct_args` for more details).
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925
"pcmpistriz128" | "pcmpistris128" => {
let [str1, str2, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [str1, str2, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let imm = this.read_scalar(imm)?.to_u8()?;
let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 };
@@ -406,7 +406,7 @@ fn emulate_x86_sse42_intrinsic(
// than 16 for byte-sized operands or 8 for word-sized operands.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047
"pcmpestriz128" | "pcmpestris128" => {
let [_, len1, _, len2, imm] = this.check_shim(abi, Conv::C, link_name, args)?;
let [_, len1, _, len2, imm] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 };
let len = this.read_scalar(len)?.to_i32()?;
let imm = this.read_scalar(imm)?.to_u8()?;
@@ -433,7 +433,7 @@ fn emulate_x86_sse42_intrinsic(
return interp_ok(EmulateItemResult::NotSupported);
}
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let left = this.read_scalar(left)?;
let right = this.read_scalar(right)?;
+8 -7
View File
@@ -1,7 +1,8 @@
use rustc_abi::CanonAbi;
use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use rustc_target::callconv::FnAbi;
use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
use crate::*;
@@ -24,7 +25,7 @@ fn emulate_x86_ssse3_intrinsic(
// Used to implement the _mm_abs_epi{8,16,32} functions.
// Calculates the absolute value of packed 8/16/32-bit integers.
"pabs.b.128" | "pabs.w.128" | "pabs.d.128" => {
let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let [op] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
int_abs(this, op, dest)?;
}
@@ -32,7 +33,7 @@ fn emulate_x86_ssse3_intrinsic(
// Shuffles bytes from `left` using `right` as pattern.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8
"pshuf.b.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -61,7 +62,7 @@ fn emulate_x86_ssse3_intrinsic(
// integer values in `left` and `right`.
"phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128"
| "phsub.d.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (which, saturating) = match unprefixed_name {
"phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false),
@@ -80,7 +81,7 @@ fn emulate_x86_ssse3_intrinsic(
// produces the output at index `i`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16
"pmadd.ub.sw.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?;
@@ -115,7 +116,7 @@ fn emulate_x86_ssse3_intrinsic(
// 1 and then taking the bits `1..=16`.
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16
"pmul.hr.sw.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
pmulhrsw(this, left, right, dest)?;
}
@@ -125,7 +126,7 @@ fn emulate_x86_ssse3_intrinsic(
// is writen to the corresponding output element.
// Basically, we multiply `left` with `right.signum()`.
"psign.b.128" | "psign.w.128" | "psign.d.128" => {
let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?;
let [left, right] = this.check_shim(abi, CanonAbi::C, link_name, args)?;
psign(this, left, right, dest)?;
}
+1 -1
View File
@@ -1,7 +1,7 @@
const UNALIGNED_READ: () = unsafe {
let x = &[0u8; 4];
let ptr = x.as_ptr().cast::<u32>();
ptr.read(); //~ERROR: evaluation of constant value failed
ptr.read(); //~ERROR: accessing memory based on pointer with alignment 1, but alignment 4 is required
};
fn main() {
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required
--> tests/fail/const-ub-checks.rs:LL:CC
|
LL | ptr.read();
| ^^^^^^^^^^ accessing memory based on pointer with alignment ALIGN, but alignment ALIGN is required
| ^^^^^^^^^^ evaluation of constant value failed here
note: erroneous constant encountered
--> tests/fail/const-ub-checks.rs:LL:CC
+1 -1
View File
@@ -4,7 +4,7 @@
struct PrintName<T>(T);
impl<T> PrintName<T> {
const VOID: ! = panic!(); //~ERROR: evaluation of `PrintName::<i32>::VOID` failed
const VOID: ! = panic!(); //~ERROR: explicit panic
}
fn no_codegen<T>() {
@@ -1,8 +1,8 @@
error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
error[E0080]: evaluation panicked: explicit panic
--> tests/fail/erroneous_const.rs:LL:CC
|
LL | const VOID: ! = panic!();
| ^^^^^^^^ evaluation panicked: explicit panic
| ^^^^^^^^ evaluation of `PrintName::<i32>::VOID` failed here
note: erroneous constant encountered
--> tests/fail/erroneous_const.rs:LL:CC
@@ -1,7 +1,7 @@
const X: u32 = 5;
const Y: u32 = 6;
const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
//~^ERROR: evaluation of constant value failed
//~^ERROR: overflow
#[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/5391
fn main() {
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: attempt to compute `5_u32 - 6_u32`, which would overflow
--> tests/fail/erroneous_const2.rs:LL:CC
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow
| ^^^^^ evaluation of constant value failed here
note: erroneous constant encountered
--> tests/fail/erroneous_const2.rs:LL:CC
+22
View File
@@ -0,0 +1,22 @@
#![feature(iter_macro, yield_expr)]
use std::iter::iter;
fn main() {
let i = iter! { || {
yield 0;
for x in 5..10 {
yield x * 2;
}
} };
let mut i = i();
assert_eq!(i.next(), Some(0));
assert_eq!(i.next(), Some(10));
assert_eq!(i.next(), Some(12));
assert_eq!(i.next(), Some(14));
assert_eq!(i.next(), Some(16));
assert_eq!(i.next(), Some(18));
assert_eq!(i.next(), None);
assert_eq!(i.next(), None);
assert_eq!(i.next(), None);
}
+2 -2
View File
@@ -4,8 +4,8 @@
use std::mem;
pub struct S {
s: Cell<usize>
s: Cell<usize>,
}
pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
//~^ ERROR evaluation of constant value failed
//~^ ERROR overflow
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: attempt to compute `0_usize - 1_usize`, which would overflow
--> $DIR/const-evalutation-ice.rs:10:22
|
LL | pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of constant value failed here
error: aborting due to 1 previous error
+3 -1
View File
@@ -59,7 +59,9 @@ error: fn_abi_of(pass_zst) = FnAbi {
},
c_variadic: false,
fixed_count: 1,
conv: X86_64SysV,
conv: X86(
SysV64,
),
can_unwind: false,
}
--> $DIR/sysv64-zst.rs:8:1
@@ -1,7 +1,6 @@
const A: &'static [i32] = &[];
const B: i32 = (&A)[1];
//~^ NOTE index out of bounds: the length is 0 but the index is 1
//~| ERROR evaluation of constant value failed
//~^ ERROR index out of bounds: the length is 0 but the index is 1
fn main() {
let _ = B;
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
error[E0080]: index out of bounds: the length is 0 but the index is 1
--> $DIR/array_const_index-0.rs:2:16
|
LL | const B: i32 = (&A)[1];
| ^^^^^^^ index out of bounds: the length is 0 but the index is 1
| ^^^^^^^ evaluation of constant value failed here
error: aborting due to 1 previous error
@@ -1,7 +1,6 @@
const A: [i32; 0] = [];
const B: i32 = A[1];
//~^ NOTE index out of bounds: the length is 0 but the index is 1
//~| ERROR evaluation of constant value failed
//~^ ERROR index out of bounds: the length is 0 but the index is 1
fn main() {
let _ = B;

Some files were not shown because too many files have changed in this diff Show More