Auto merge of #145074 - tgross35:rollup-0tillrm, r=tgross35

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#144705 (compiler-builtins: plumb LSE support for aarch64 on linux/gnu when optimized-compiler-builtins not enabled)
 - rust-lang/rust#144857 (Port `#[allow_internal_unsafe]` to the new attribute system)
 - rust-lang/rust#144900 (Stabilize `unsigned_signed_diff` feature)
 - rust-lang/rust#144903 (Rename `begin_panic_handler` to `panic_handler`)
 - rust-lang/rust#144974 (compiler-builtins subtree update)
 - rust-lang/rust#145007 (Fix build/doc/test of error index generator)
 - rust-lang/rust#145018 (Derive `Hash` for rustc_public types)
 - rust-lang/rust#145045 (doc(library): Fix Markdown in `Iterator::by_ref`)
 - rust-lang/rust#145046 (Fix doc comment of File::try_lock and File::try_lock_shared)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-08-08 02:59:15 +00:00
197 changed files with 825 additions and 716 deletions
@@ -113,3 +113,11 @@ fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
}
}
pub(crate) struct AllowInternalUnsafeParser;
impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
}
+4 -1
View File
@@ -33,7 +33,9 @@
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser};
use crate::attributes::macro_attrs::{
AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
@@ -178,6 +180,7 @@ mod late {
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
Single<WithoutArgs<AllowIncoherentImplParser>>,
Single<WithoutArgs<AllowInternalUnsafeParser>>,
Single<WithoutArgs<AsPtrParser>>,
Single<WithoutArgs<AutomaticallyDerivedParser>>,
Single<WithoutArgs<CoherenceIsCoreParser>>,
+1 -4
View File
@@ -905,10 +905,7 @@ pub fn new(
find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i)
.map(|i| i.as_slice())
.unwrap_or_default();
// FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style
// let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe);
let allow_internal_unsafe =
ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some();
let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_));
let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
.and_then(|macro_export| macro_export.meta_item_list())
@@ -249,6 +249,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_allow_incoherent_impl]`.
AllowIncoherentImpl(Span),
/// Represents `#[allow_internal_unsafe]`.
AllowInternalUnsafe(Span),
/// Represents `#[allow_internal_unstable]`.
AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
@@ -16,6 +16,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
Align { .. } => No,
AllowConstFnUnstable(..) => No,
AllowIncoherentImpl(..) => No,
AllowInternalUnsafe(..) => Yes,
AllowInternalUnstable(..) => Yes,
AsPtr(..) => Yes,
AutomaticallyDerived(..) => Yes,
+12 -1
View File
@@ -14,6 +14,7 @@
//! [`crate::late_lint_methods!`] invocation in `lib.rs`.
use std::fmt::Write;
use std::slice;
use ast::token::TokenKind;
use rustc_abi::BackendRepr;
@@ -21,6 +22,7 @@
use rustc_ast::visit::{FnCtxt, FnKind};
use rustc_ast::{self as ast, *};
use rustc_ast_pretty::pprust::expr_to_string;
use rustc_attr_parsing::AttributeParser;
use rustc_errors::{Applicability, LintDiagnostic};
use rustc_feature::GateIssue;
use rustc_hir as hir;
@@ -249,7 +251,16 @@ fn report_unsafe(
impl EarlyLintPass for UnsafeCode {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
if attr.has_name(sym::allow_internal_unsafe) {
if AttributeParser::parse_limited(
cx.builder.sess(),
slice::from_ref(attr),
sym::allow_internal_unsafe,
attr.span,
DUMMY_NODE_ID,
Some(cx.builder.features()),
)
.is_some()
{
self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe);
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ passes_allow_incoherent_impl =
`rustc_allow_incoherent_impl` attribute should be applied to impl items
.label = the only currently supported targets are inherent methods
passes_allow_internal_unstable =
passes_macro_only_attribute =
attribute should be applied to a macro
.label = not a macro
+41 -8
View File
@@ -207,6 +207,9 @@ fn check_attributes(
Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => {
self.check_const_continue(hir_id, *attr_span, target)
}
Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => {
self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs)
}
Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => {
self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs)
}
@@ -413,7 +416,6 @@ fn check_attributes(
// internal
| sym::prelude_import
| sym::panic_handler
| sym::allow_internal_unsafe
| sym::lang
| sym::needs_allocator
| sym::default_lib_allocator
@@ -2212,7 +2214,6 @@ fn check_used(&self, attr_span: Span, target: Target, target_span: Span) {
/// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
/// (Allows proc_macro functions)
// FIXME(jdonszelmann): if possible, move to attr parsing
fn check_allow_internal_unstable(
&self,
hir_id: HirId,
@@ -2220,6 +2221,42 @@ fn check_allow_internal_unstable(
span: Span,
target: Target,
attrs: &[Attribute],
) {
self.check_macro_only_attr(
hir_id,
attr_span,
span,
target,
attrs,
"allow_internal_unstable",
)
}
/// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros.
/// (Allows proc_macro functions)
fn check_allow_internal_unsafe(
&self,
hir_id: HirId,
attr_span: Span,
span: Span,
target: Target,
attrs: &[Attribute],
) {
self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe")
}
/// Outputs an error for attributes that can only be applied to macros, such as
/// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`.
/// (Allows proc_macro functions)
// FIXME(jdonszelmann): if possible, move to attr parsing
fn check_macro_only_attr(
&self,
hir_id: HirId,
attr_span: Span,
span: Span,
target: Target,
attrs: &[Attribute],
attr_name: &str,
) {
match target {
Target::Fn => {
@@ -2238,18 +2275,14 @@ fn check_allow_internal_unstable(
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm => {
self.inline_attr_str_error_without_macro_def(
hir_id,
attr_span,
"allow_internal_unstable",
);
self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name);
return;
}
// otherwise continue out of the match
_ => {}
}
self.tcx.dcx().emit_err(errors::AllowInternalUnstable { attr_span, span });
self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span });
}
/// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
+2 -2
View File
@@ -643,8 +643,8 @@ pub(crate) struct UsedStatic {
}
#[derive(Diagnostic)]
#[diag(passes_allow_internal_unstable)]
pub(crate) struct AllowInternalUnstable {
#[diag(passes_macro_only_attribute)]
pub(crate) struct MacroOnlyAttribute {
#[primary_span]
pub attr_span: Span,
#[label]
+16 -16
View File
@@ -349,7 +349,7 @@ pub fn description(&self) -> Result<&'static str, Error> {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum BinOp {
Add,
AddUnchecked,
@@ -384,7 +384,7 @@ pub fn ty(&self, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum UnOp {
Not,
Neg,
@@ -490,7 +490,7 @@ pub enum StatementKind {
Nop,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum Rvalue {
/// Creates a pointer with the indicated mutability to the place.
///
@@ -666,7 +666,7 @@ pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum AggregateKind {
Array(Ty),
Tuple,
@@ -677,14 +677,14 @@ pub enum AggregateKind {
RawPtr(Ty, Mutability),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum Operand {
Copy(Place),
Move(Place),
Constant(ConstOperand),
}
#[derive(Clone, Eq, PartialEq, Serialize)]
#[derive(Clone, Eq, PartialEq, Hash, Serialize)]
pub struct Place {
pub local: Local,
/// projection out of a place (access a field, deref a pointer, etc)
@@ -697,7 +697,7 @@ fn from(local: Local) -> Self {
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct ConstOperand {
pub span: Span,
pub user_ty: Option<UserTypeAnnotationIndex>,
@@ -770,7 +770,7 @@ pub enum VarDebugInfoContents {
// ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
// are of type ProjectionElem<(), ()>).
// In rustc_public's IR we don't need this generality, so we just use ProjectionElem for Places.
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum ProjectionElem {
/// Dereference projections (e.g. `*_1`) project to the address referenced by the base place.
Deref,
@@ -913,7 +913,7 @@ pub fn new(branches: Vec<(u128, BasicBlockIdx)>, otherwise: BasicBlockIdx) -> Sw
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
Shared,
@@ -940,7 +940,7 @@ pub fn to_mutable_lossy(self) -> Mutability {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum RawPtrKind {
Mut,
Const,
@@ -958,14 +958,14 @@ pub fn to_mutable_lossy(self) -> Mutability {
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum MutBorrowKind {
Default,
TwoPhaseBorrow,
ClosureCapture,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum FakeBorrowKind {
/// A shared (deep) borrow. Data must be immutable and is aliasable.
Deep,
@@ -982,13 +982,13 @@ pub enum Mutability {
Mut,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum Safety {
Safe,
Unsafe,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum PointerCoercion {
/// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
@@ -1015,7 +1015,7 @@ pub enum PointerCoercion {
Unsize,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum CastKind {
// FIXME(smir-rename): rename this to PointerExposeProvenance
PointerExposeAddress,
@@ -1030,7 +1030,7 @@ pub enum CastKind {
Transmute,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum NullOp {
/// Returns the size of a value of that type.
SizeOf,
+17 -17
View File
@@ -113,7 +113,7 @@ pub enum Pattern {
}
/// Represents a constant in the type system
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct TyConst {
pub(crate) kind: TyConstKind,
pub id: TyConstId,
@@ -140,7 +140,7 @@ pub fn eval_target_usize(&self) -> Result<u64, Error> {
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum TyConstKind {
Param(ParamConst),
Bound(DebruijnIndex, BoundVar),
@@ -151,11 +151,11 @@ pub enum TyConstKind {
ZSTValue(Ty),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct TyConstId(usize);
/// Represents a constant in MIR
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct MirConst {
/// The constant kind.
pub(crate) kind: ConstantKind,
@@ -212,17 +212,17 @@ pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct MirConstId(usize);
type Ident = Opaque;
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct Region {
pub kind: RegionKind,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum RegionKind {
ReEarlyParam(EarlyParamRegion),
ReBound(DebruijnIndex, BoundRegion),
@@ -233,7 +233,7 @@ pub enum RegionKind {
pub(crate) type DebruijnIndex = u32;
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct EarlyParamRegion {
pub index: u32,
pub name: Symbol,
@@ -241,7 +241,7 @@ pub struct EarlyParamRegion {
pub(crate) type BoundVar = u32;
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct BoundRegion {
pub var: BoundVar,
pub kind: BoundRegionKind,
@@ -249,13 +249,13 @@ pub struct BoundRegion {
pub(crate) type UniverseIndex = u32;
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
pub bound: T,
}
#[derive(Clone, Copy, PartialEq, Eq, Serialize)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize)]
pub struct Span(usize);
impl Debug for Span {
@@ -997,7 +997,7 @@ pub fn trait_impl(&self) -> ImplTrait {
}
/// A list of generic arguments.
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct GenericArgs(pub Vec<GenericArgKind>);
impl std::ops::Index<ParamTy> for GenericArgs {
@@ -1016,7 +1016,7 @@ fn index(&self, index: ParamConst) -> &Self::Output {
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum GenericArgKind {
Lifetime(Region),
Type(Ty),
@@ -1199,7 +1199,7 @@ pub enum BoundTyKind {
Param(ParamDef, String),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum BoundRegionKind {
BrAnon,
BrNamed(BrNamedDef, String),
@@ -1354,7 +1354,7 @@ pub fn is_null(&self) -> Result<bool, Error> {
}
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub enum ConstantKind {
Ty(TyConst),
Allocated(Allocation),
@@ -1365,13 +1365,13 @@ pub enum ConstantKind {
ZeroSized,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct ParamConst {
pub index: u32,
pub name: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
pub struct UnevaluatedConst {
pub def: ConstDef,
pub args: GenericArgs,
+29 -9
View File
@@ -34,7 +34,9 @@ jobs:
- name: Fetch pull request ref
run: git fetch origin "$GITHUB_REF:$GITHUB_REF"
if: github.event_name == 'pull_request'
- run: python3 ci/ci-util.py generate-matrix >> "$GITHUB_OUTPUT"
- run: |
set -eo pipefail # Needed to actually fail the job if ci-util fails
python3 ci/ci-util.py generate-matrix | tee "$GITHUB_OUTPUT"
id: script
test:
@@ -50,7 +52,6 @@ jobs:
os: ubuntu-24.04-arm
- target: aarch64-pc-windows-msvc
os: windows-2025
test_verbatim: 1
build_only: 1
- target: arm-unknown-linux-gnueabi
os: ubuntu-24.04
@@ -70,8 +71,12 @@ jobs:
os: ubuntu-24.04
- target: powerpc64le-unknown-linux-gnu
os: ubuntu-24.04
- target: powerpc64le-unknown-linux-gnu
os: ubuntu-24.04-ppc64le
- target: riscv64gc-unknown-linux-gnu
os: ubuntu-24.04
- target: s390x-unknown-linux-gnu
os: ubuntu-24.04-s390x
- target: thumbv6m-none-eabi
os: ubuntu-24.04
- target: thumbv7em-none-eabi
@@ -88,10 +93,8 @@ jobs:
os: macos-13
- target: i686-pc-windows-msvc
os: windows-2025
test_verbatim: 1
- target: x86_64-pc-windows-msvc
os: windows-2025
test_verbatim: 1
- target: i686-pc-windows-gnu
os: windows-2025
channel: nightly-i686-gnu
@@ -102,11 +105,23 @@ jobs:
needs: [calculate_vars]
env:
BUILD_ONLY: ${{ matrix.build_only }}
TEST_VERBATIM: ${{ matrix.test_verbatim }}
MAY_SKIP_LIBM_CI: ${{ needs.calculate_vars.outputs.may_skip_libm_ci }}
steps:
- name: Print $HOME
shell: bash
run: |
set -x
echo "${HOME:-not found}"
pwd
printenv
- name: Print runner information
run: uname -a
# Native ppc and s390x runners don't have rustup by default
- name: Install rustup
if: matrix.os == 'ubuntu-24.04-ppc64le' || matrix.os == 'ubuntu-24.04-s390x'
run: sudo apt-get update && sudo apt-get install -y rustup
- uses: actions/checkout@v4
- name: Install Rust (rustup)
shell: bash
@@ -117,7 +132,12 @@ jobs:
rustup update "$channel" --no-self-update
rustup default "$channel"
rustup target add "${{ matrix.target }}"
# Our scripts use nextest if possible. This is skipped on the native ppc
# and s390x runners since install-action doesn't support them.
- uses: taiki-e/install-action@nextest
if: "!(matrix.os == 'ubuntu-24.04-ppc64le' || matrix.os == 'ubuntu-24.04-s390x')"
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
@@ -144,7 +164,7 @@ jobs:
shell: bash
- run: echo "RUST_COMPILER_RT_ROOT=$(realpath ./compiler-rt)" >> "$GITHUB_ENV"
shell: bash
- name: Download musl source
run: ./ci/update-musl.sh
shell: bash
@@ -256,7 +276,7 @@ jobs:
with:
name: ${{ env.BASELINE_NAME }}
path: ${{ env.BASELINE_NAME }}.tar.xz
- name: Run wall time benchmarks
run: |
# Always use the same seed for benchmarks. Ideally we should switch to a
@@ -311,8 +331,8 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Install stable `rustfmt`
run: rustup set profile minimal && rustup default stable && rustup component add rustfmt
- name: Install nightly `rustfmt`
run: rustup set profile minimal && rustup default nightly && rustup component add rustfmt
- run: cargo fmt -- --check
extensive:
+3 -2
View File
@@ -12,12 +12,13 @@ jobs:
if: github.repository == 'rust-lang/compiler-builtins'
uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@main
with:
github-app-id: ${{ vars.APP_CLIENT_ID }}
# https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/compiler-builtins.20subtree.20sync.20automation/with/528482375
zulip-stream-id: 219381
zulip-topic: 'compiler-builtins subtree sync automation'
zulip-bot-email: "compiler-builtins-ci-bot@rust-lang.zulipchat.com"
zulip-bot-email: "compiler-builtins-ci-bot@rust-lang.zulipchat.com"
pr-base-branch: master
branch-name: rustc-pull
secrets:
zulip-api-token: ${{ secrets.ZULIP_API_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
github-app-secret: ${{ secrets.APP_PRIVATE_KEY }}
@@ -37,8 +37,9 @@ default = ["compiler-builtins"]
# implementations and also filling in unimplemented intrinsics
c = ["dep:cc"]
# Workaround for the Cranelift codegen backend. Disables any implementations
# which use inline assembly and fall back to pure Rust versions (if available).
# For implementations where there is both a generic version and a platform-
# specific version, use the generic version. This is meant to enable testing
# the generic versions on all platforms.
no-asm = []
# Workaround for codegen backends which haven't yet implemented `f16` and
@@ -40,11 +40,7 @@ pub fn extendhfdf(x: f16) -> f64 {
x as f64
}
#[cfg(all(
f16_enabled,
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(all(f16_enabled, f128_enabled))]
pub fn extendhftf(x: f16) -> f128 {
x as f128
}
@@ -201,11 +197,7 @@ pub fn aeabi_dsub(a: f64, b: f64) -> f64 {
/* f128 operations */
#[cfg(all(
f16_enabled,
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(all(f16_enabled, f128_enabled))]
pub fn trunctfhf(x: f128) -> f16 {
x as f16
}
@@ -220,50 +212,32 @@ pub fn trunctfdf(x: f128) -> f64 {
x as f64
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixtfsi(x: f128) -> i32 {
x as i32
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixtfdi(x: f128) -> i64 {
x as i64
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixtfti(x: f128) -> i128 {
x as i128
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixunstfsi(x: f128) -> u32 {
x as u32
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixunstfdi(x: f128) -> u64 {
x as u64
}
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
pub fn fixunstfti(x: f128) -> u128 {
x as u128
}
@@ -540,47 +514,25 @@ fn run() {
bb(extendhfdf(bb(2.)));
#[cfg(f16_enabled)]
bb(extendhfsf(bb(2.)));
#[cfg(all(
f16_enabled,
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(all(f16_enabled, f128_enabled))]
bb(extendhftf(bb(2.)));
#[cfg(f128_enabled)]
bb(extendsftf(bb(2.)));
bb(fixdfti(bb(2.)));
bb(fixsfti(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixtfdi(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixtfsi(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixtfti(bb(2.)));
bb(fixunsdfti(bb(2.)));
bb(fixunssfti(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixunstfdi(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixunstfsi(bb(2.)));
#[cfg(all(
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(f128_enabled)]
bb(fixunstfti(bb(2.)));
#[cfg(f128_enabled)]
bb(floatditf(bb(2)));
@@ -616,11 +568,7 @@ fn run() {
bb(truncsfhf(bb(2.)));
#[cfg(f128_enabled)]
bb(trunctfdf(bb(2.)));
#[cfg(all(
f16_enabled,
f128_enabled,
not(any(target_arch = "powerpc", target_arch = "powerpc64"))
))]
#[cfg(all(f16_enabled, f128_enabled))]
bb(trunctfhf(bb(2.)));
#[cfg(f128_enabled)]
bb(trunctfsf(bb(2.)));
@@ -365,7 +365,6 @@
/* float -> unsigned int */
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_u32,
sig: (a: f32) -> u32,
@@ -387,7 +386,6 @@
],
}
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_u64,
sig: (a: f32) -> u64,
@@ -409,7 +407,6 @@
],
}
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_u128,
sig: (a: f32) -> u128,
@@ -505,7 +502,6 @@
/* float -> signed int */
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_i32,
sig: (a: f32) -> i32,
@@ -527,7 +523,6 @@
],
}
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_i64,
sig: (a: f32) -> i64,
@@ -549,7 +544,6 @@
],
}
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
float_bench! {
name: conv_f32_i128,
sig: (a: f32) -> i128,
@@ -666,9 +660,6 @@ pub fn float_conv() {
conv_f64_i128(&mut criterion);
#[cfg(f128_enabled)]
// FIXME: ppc64le has a sporadic overflow panic in the crate functions
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2125914639>
#[cfg(not(all(target_arch = "powerpc64", target_endian = "little")))]
{
conv_u32_f128(&mut criterion);
conv_u64_f128(&mut criterion);
@@ -110,9 +110,7 @@
pub fn float_extend() {
let mut criterion = Criterion::default().configure_from_args();
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
{
extend_f16_f32(&mut criterion);
extend_f16_f64(&mut criterion);
@@ -121,9 +121,7 @@
pub fn float_trunc() {
let mut criterion = Criterion::default().configure_from_args();
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
{
trunc_f32_f16(&mut criterion);
trunc_f64_f16(&mut criterion);
@@ -133,11 +131,8 @@ pub fn float_trunc() {
#[cfg(f128_enabled)]
{
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
#[cfg(f16_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
trunc_f128_f16(&mut criterion);
trunc_f128_f32(&mut criterion);
trunc_f128_f64(&mut criterion);
}
@@ -17,28 +17,14 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
"extend_f16_f32",
"trunc_f32_f16",
"trunc_f64_f16",
// FIXME(#616): re-enable once fix is in nightly
// <https://github.com/rust-lang/compiler-builtins/issues/616>
"mul_f32",
"mul_f64",
];
// FIXME(f16_f128): error on LE ppc64. There are more tests that are cfg-ed out completely
// in their benchmark modules due to runtime panics.
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2125914639>
const PPC64LE_SKIPPED: &[&str] = &["extend_f32_f128"];
// FIXME(f16_f128): system symbols have incorrect results
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2125914639>
const X86_NO_SSE_SKIPPED: &[&str] = &[
"add_f128", "sub_f128", "mul_f128", "div_f128", "powi_f32", "powi_f64",
];
// FIXME(f16_f128): Wide multiply carry bug in `compiler-rt`, re-enable when nightly no longer
// uses `compiler-rt` version.
// <https://github.com/llvm/llvm-project/issues/91840>
const AARCH64_SKIPPED: &[&str] = &["mul_f128", "div_f128"];
// FIXME(llvm): system symbols have incorrect results on Windows
// <https://github.com/rust-lang/compiler-builtins/issues/617#issuecomment-2121359807>
const WINDOWS_SKIPPED: &[&str] = &[
@@ -57,19 +43,7 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
return true;
}
if cfg!(all(target_arch = "powerpc64", target_endian = "little"))
&& PPC64LE_SKIPPED.contains(&test_name)
{
return true;
}
if cfg!(all(target_arch = "x86", not(target_feature = "sse")))
&& X86_NO_SSE_SKIPPED.contains(&test_name)
{
return true;
}
if cfg!(target_arch = "aarch64") && AARCH64_SKIPPED.contains(&test_name) {
if cfg!(x86_no_sse) && X86_NO_SSE_SKIPPED.contains(&test_name) {
return true;
}
@@ -111,7 +111,7 @@ fn $fn_add() {
}
}
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(x86_no_sse))]
mod float_addsub {
use super::*;
@@ -122,7 +122,7 @@ mod float_addsub {
}
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(x86_no_sse))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_addsub_f128 {
use super::*;
@@ -59,32 +59,28 @@ fn $fn() {
|| ((error_minus == error || error_plus == error)
&& ((f0.to_bits() & 1) != 0))
{
if !cfg!(any(
target_arch = "powerpc",
target_arch = "powerpc64"
)) {
panic!(
"incorrect rounding by {}({}): {}, ({}, {}, {}), errors ({}, {}, {})",
stringify!($fn),
x,
f1.to_bits(),
y_minus_ulp,
y,
y_plus_ulp,
error_minus,
error,
error_plus,
);
}
panic!(
"incorrect rounding by {}({}): {}, ({}, {}, {}), errors ({}, {}, {})",
stringify!($fn),
x,
f1.to_bits(),
y_minus_ulp,
y,
y_plus_ulp,
error_minus,
error,
error_plus,
);
}
}
// Test against native conversion. We disable testing on all `x86` because of
// rounding bugs with `i686`. `powerpc` also has the same rounding bug.
// Test against native conversion.
// FIXME(x86,ppc): the platform version has rounding bugs on i686 and
// PowerPC64le (for PPC this only shows up in Docker, not the native runner).
// https://github.com/rust-lang/compiler-builtins/pull/384#issuecomment-740413334
if !Float::eq_repr(f0, f1) && !cfg!(any(
target_arch = "x86",
target_arch = "powerpc",
target_arch = "powerpc64"
all(target_arch = "powerpc64", target_endian = "little")
)) {
panic!(
"{}({}): std: {:?}, builtins: {:?}",
@@ -138,7 +138,7 @@ fn $fn() {
};
}
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(x86_no_sse))]
mod float_div {
use super::*;
@@ -1,7 +1,7 @@
#![allow(unused_macros)]
#![cfg_attr(f128_enabled, feature(f128))]
#![cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg_attr(x86_no_sse, allow(unused))]
use builtins_test::*;
// This is approximate because of issues related to
@@ -52,6 +52,7 @@ fn $fn() {
};
}
#[cfg(not(x86_no_sse))] // FIXME(i586): failure for powidf2
pow! {
f32, 1e-4, __powisf2, all();
f64, 1e-12, __powidf2, all();
@@ -1,6 +1,6 @@
#![feature(decl_macro)] // so we can use pub(super)
#![feature(macro_metavar_expr_concat)]
#![cfg(all(target_arch = "aarch64", target_os = "linux", not(feature = "no-asm")))]
#![cfg(all(target_arch = "aarch64", target_os = "linux"))]
/// Translate a byte size to a Rust type.
macro int_ty {
@@ -113,7 +113,7 @@ fn $fn() {
};
}
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(x86_no_sse))]
mod float_mul {
use super::*;
@@ -126,7 +126,7 @@ mod float_mul {
}
#[cfg(f128_enabled)]
#[cfg(not(all(target_arch = "x86", not(target_feature = "sse"))))]
#[cfg(not(x86_no_sse))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_mul_f128 {
use super::*;
+89 -37
View File
@@ -7,10 +7,12 @@ git history.
import json
import os
import pprint
import re
import subprocess as sp
import sys
from dataclasses import dataclass
from functools import cache
from glob import glob
from inspect import cleandoc
from os import getenv
@@ -50,15 +52,6 @@ GIT = ["git", "-C", REPO_ROOT]
DEFAULT_BRANCH = "master"
WORKFLOW_NAME = "CI" # Workflow that generates the benchmark artifacts
ARTIFACT_PREFIX = "baseline-icount*"
# Place this in a PR body to skip regression checks (must be at the start of a line).
REGRESSION_DIRECTIVE = "ci: allow-regressions"
# Place this in a PR body to skip extensive tests
SKIP_EXTENSIVE_DIRECTIVE = "ci: skip-extensive"
# Place this in a PR body to allow running a large number of extensive tests. If not
# set, this script will error out if a threshold is exceeded in order to avoid
# accidentally spending huge amounts of CI time.
ALLOW_MANY_EXTENSIVE_DIRECTIVE = "ci: allow-many-extensive"
MANY_EXTENSIVE_THRESHOLD = 20
# Don't run exhaustive tests if these files change, even if they contaiin a function
# definition.
@@ -70,7 +63,7 @@ IGNORE_FILES = [
# libm PR CI takes a long time and doesn't need to run unless relevant files have been
# changed. Anything matching this regex pattern will trigger a run.
TRIGGER_LIBM_PR_CI = ".*(libm|musl).*"
TRIGGER_LIBM_CI_FILE_PAT = ".*(libm|musl).*"
TYPES = ["f16", "f32", "f64", "f128"]
@@ -80,6 +73,54 @@ def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
@dataclass(init=False)
class PrCfg:
"""Directives that we allow in the commit body to control test behavior.
These are of the form `ci: foo`, at the start of a line.
"""
# Skip regression checks (must be at the start of a line).
allow_regressions: bool = False
# Don't run extensive tests
skip_extensive: bool = False
# Allow running a large number of extensive tests. If not set, this script
# will error out if a threshold is exceeded in order to avoid accidentally
# spending huge amounts of CI time.
allow_many_extensive: bool = False
# Max number of extensive tests to run by default
MANY_EXTENSIVE_THRESHOLD: int = 20
# Run tests for `libm` that may otherwise be skipped due to no changed files.
always_test_libm: bool = False
# String values of directive names
DIR_ALLOW_REGRESSIONS: str = "allow-regressions"
DIR_SKIP_EXTENSIVE: str = "skip-extensive"
DIR_ALLOW_MANY_EXTENSIVE: str = "allow-many-extensive"
DIR_TEST_LIBM: str = "test-libm"
def __init__(self, body: str):
directives = re.finditer(r"^\s*ci:\s*(?P<dir_name>\S*)", body, re.MULTILINE)
for dir in directives:
name = dir.group("dir_name")
if name == self.DIR_ALLOW_REGRESSIONS:
self.allow_regressions = True
elif name == self.DIR_SKIP_EXTENSIVE:
self.skip_extensive = True
elif name == self.DIR_ALLOW_MANY_EXTENSIVE:
self.allow_many_extensive = True
elif name == self.DIR_TEST_LIBM:
self.always_test_libm = True
else:
eprint(f"Found unexpected directive `{name}`")
exit(1)
pprint.pp(self)
@dataclass
class PrInfo:
"""GitHub response for PR query"""
@@ -88,10 +129,21 @@ class PrInfo:
commits: list[str]
created_at: str
number: int
cfg: PrCfg
@classmethod
def load(cls, pr_number: int | str) -> Self:
"""For a given PR number, query the body and commit list"""
def from_env(cls) -> Self | None:
"""Create a PR object from the PR_NUMBER environment if set, `None` otherwise."""
pr_env = os.environ.get("PR_NUMBER")
if pr_env is not None and len(pr_env) > 0:
return cls.from_pr(pr_env)
return None
@classmethod
@cache # Cache so we don't print info messages multiple times
def from_pr(cls, pr_number: int | str) -> Self:
"""For a given PR number, query the body and commit list."""
pr_info = sp.check_output(
[
"gh",
@@ -104,13 +156,9 @@ class PrInfo:
],
text=True,
)
eprint("PR info:", json.dumps(pr_info, indent=4))
return cls(**json.loads(pr_info))
def contains_directive(self, directive: str) -> bool:
"""Return true if the provided directive is on a line in the PR body"""
lines = self.body.splitlines()
return any(line.startswith(directive) for line in lines)
pr_json = json.loads(pr_info)
eprint("PR info:", json.dumps(pr_json, indent=4))
return cls(**json.loads(pr_info), cfg=PrCfg(pr_json["body"]))
class FunctionDef(TypedDict):
@@ -207,26 +255,32 @@ class Context:
"""If this is a PR and no libm files were changed, allow skipping libm
jobs."""
if self.is_pr():
return all(not re.match(TRIGGER_LIBM_PR_CI, str(f)) for f in self.changed)
# Always run on merge CI
if not self.is_pr():
return False
return False
pr = PrInfo.from_env()
assert pr is not None, "Is a PR but couldn't load PrInfo"
# Allow opting in to libm tests
if pr.cfg.always_test_libm:
return False
# By default, run if there are any changed files matching the pattern
return all(not re.match(TRIGGER_LIBM_CI_FILE_PAT, str(f)) for f in self.changed)
def emit_workflow_output(self):
"""Create a JSON object a list items for each type's changed files, if any
did change, and the routines that were affected by the change.
"""
pr_number = os.environ.get("PR_NUMBER")
skip_tests = False
error_on_many_tests = False
if pr_number is not None and len(pr_number) > 0:
pr = PrInfo.load(pr_number)
skip_tests = pr.contains_directive(SKIP_EXTENSIVE_DIRECTIVE)
error_on_many_tests = not pr.contains_directive(
ALLOW_MANY_EXTENSIVE_DIRECTIVE
)
pr = PrInfo.from_env()
if pr is not None:
skip_tests = pr.cfg.skip_extensive
error_on_many_tests = not pr.cfg.allow_many_extensive
if skip_tests:
eprint("Skipping all extensive tests")
@@ -253,16 +307,14 @@ class Context:
may_skip = str(self.may_skip_libm_ci()).lower()
print(f"extensive_matrix={ext_matrix}")
print(f"may_skip_libm_ci={may_skip}")
eprint(f"extensive_matrix={ext_matrix}")
eprint(f"may_skip_libm_ci={may_skip}")
eprint(f"total extensive tests: {total_to_test}")
if error_on_many_tests and total_to_test > MANY_EXTENSIVE_THRESHOLD:
if error_on_many_tests and total_to_test > PrCfg.MANY_EXTENSIVE_THRESHOLD:
eprint(
f"More than {MANY_EXTENSIVE_THRESHOLD} tests would be run; add"
f" `{ALLOW_MANY_EXTENSIVE_DIRECTIVE}` to the PR body if this is"
f"More than {PrCfg.MANY_EXTENSIVE_THRESHOLD} tests would be run; add"
f" `{PrCfg.DIR_ALLOW_MANY_EXTENSIVE}` to the PR body if this is"
" intentional. If this is refactoring that happens to touch a lot of"
f" files, `{SKIP_EXTENSIVE_DIRECTIVE}` can be used instead."
f" files, `{PrCfg.DIR_SKIP_EXTENSIVE}` can be used instead."
)
exit(1)
@@ -371,8 +423,8 @@ def handle_bench_regressions(args: list[str]):
eprint(USAGE)
exit(1)
pr = PrInfo.load(pr_number)
if pr.contains_directive(REGRESSION_DIRECTIVE):
pr = PrInfo.from_pr(pr_number)
if pr.cfg.allow_regressions:
eprint("PR allows regressions")
return
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -12,6 +12,5 @@ ENV CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \
CARGO_TARGET_POWERPC64LE_UNKNOWN_LINUX_GNU_RUNNER=qemu-ppc64le-static \
AR_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"ar \
CC_powerpc64le_unknown_linux_gnu="$TOOLCHAIN_PREFIX"gcc \
QEMU_CPU=POWER8 \
QEMU_LD_PREFIX=/usr/powerpc64le-linux-gnu \
RUST_TEST_THREADS=1
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:24.04
ARG IMAGE=ubuntu:25.04
FROM $IMAGE
RUN apt-get update && \
+1 -1
View File
@@ -97,7 +97,7 @@ if [ "${1:-}" = "--help" ] || [ "$#" -gt 1 ]; then
usage: ./ci/run-docker.sh [target]
you can also set DOCKER_BASE_IMAGE to use something other than the default
ubuntu:24.04 (or rustlang/rust:nightly).
ubuntu:25.04 (or rustlang/rust:nightly).
"
exit
fi
+6 -3
View File
@@ -41,7 +41,10 @@ else
"${test_builtins[@]}" --benches
"${test_builtins[@]}" --benches --release
if [ "${TEST_VERBATIM:-}" = "1" ]; then
# Validate that having a verbatim path for the target directory works
# (trivial to regress using `/` in paths to build artifacts rather than
# `Path::join`). MinGW does not currently support these paths.
if [[ "$target" = *"windows"* ]] && [[ "$target" != *"gnu"* ]]; then
verb_path=$(cmd.exe //C echo \\\\?\\%cd%\\builtins-test\\target2)
"${test_builtins[@]}" --target-dir "$verb_path" --features c
fi
@@ -161,7 +164,7 @@ else
mflags+=(--workspace --target "$target")
cmd=(cargo test "${mflags[@]}")
profile_flag="--profile"
# If nextest is available, use that
command -v cargo-nextest && nextest=1 || nextest=0
if [ "$nextest" = "1" ]; then
@@ -204,7 +207,7 @@ else
"${cmd[@]}" "$profile_flag" release-checked --features unstable-intrinsics --benches
# Ensure that the routines do not panic.
#
#
# `--tests` must be passed because no-panic is only enabled as a dev
# dependency. The `release-opt` profile must be used to enable LTO and a
# single CGU.
+1 -1
View File
@@ -3,7 +3,7 @@
set -eux
url=git://git.musl-libc.org/musl
url=https://github.com/kraj/musl.git
ref=c47ad25ea3b484e10326f933e927c0bc8cded3da
dst=crates/musl-math-sys/musl
@@ -35,8 +35,9 @@ default = ["compiler-builtins"]
# implementations and also filling in unimplemented intrinsics
c = ["dep:cc"]
# Workaround for the Cranelift codegen backend. Disables any implementations
# which use inline assembly and fall back to pure Rust versions (if available).
# For implementations where there is both a generic version and a platform-
# specific version, use the generic version. This is meant to enable testing
# the generic versions on all platforms.
no-asm = []
# Workaround for codegen backends which haven't yet implemented `f16` and
@@ -106,13 +106,6 @@ fn configure_libm(target: &Target) {
println!("cargo:rustc-cfg=optimizations_enabled");
}
// Config shorthands
println!("cargo:rustc-check-cfg=cfg(x86_no_sse)");
if target.arch == "x86" && !target.features.iter().any(|f| f == "sse") {
// Shorthand to detect i586 targets
println!("cargo:rustc-cfg=x86_no_sse");
}
println!(
"cargo:rustc-env=CFG_CARGO_FEATURES={:?}",
target.cargo_features
@@ -1,6 +1,5 @@
// Configuration that is shared between `compiler_builtins` and `builtins_test`.
use std::process::{Command, Stdio};
use std::{env, str};
#[derive(Debug)]
@@ -35,26 +34,6 @@ pub fn from_env() -> Self {
.map(|s| s.to_lowercase().replace("_", "-"))
.collect();
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
// on stable otherwise).
let mut cmd = Command::new(env::var("RUSTC").unwrap());
cmd.args(["--print=cfg", "--target", &triple])
.env("RUSTC_BOOTSTRAP", "1")
.stderr(Stdio::inherit());
let out = cmd
.output()
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
// If we couldn't query `rustc` (e.g. a custom JSON target was used), make the safe
// choice and leave `f16` and `f128` disabled.
let rustc_output_ok = out.status.success();
let reliable_f128 =
rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f128");
let reliable_f16 =
rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f16");
Self {
triple,
triple_split,
@@ -74,8 +53,10 @@ pub fn from_env() -> Self {
.split(",")
.map(ToOwned::to_owned)
.collect(),
reliable_f128,
reliable_f16,
// Note that these are unstable options, so only show up with the nightly compiler or
// with `RUSTC_BOOTSTRAP=1` (which is required to use the types anyway).
reliable_f128: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F128").is_some(),
reliable_f16: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F16").is_some(),
}
}
@@ -100,6 +81,13 @@ pub fn configure_aliases(target: &Target) {
println!("cargo:rustc-cfg=thumb_1")
}
// Config shorthands
println!("cargo:rustc-check-cfg=cfg(x86_no_sse)");
if target.arch == "x86" && !target.features.iter().any(|f| f == "sse") {
// Shorthand to detect i586 targets
println!("cargo:rustc-cfg=x86_no_sse");
}
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
* need to disable things if the compiler may crash. See configuration at:
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
@@ -4,7 +4,7 @@
intrinsics! {
#[unsafe(naked)]
#[cfg(all(target_os = "uefi", not(feature = "no-asm")))]
#[cfg(target_os = "uefi")]
pub unsafe extern "custom" fn __chkstk() {
core::arch::naked_asm!(
".p2align 2",
@@ -6,9 +6,6 @@
//! which is supported on the current CPU.
//! See <https://community.arm.com/arm-community-blogs/b/tools-software-ides-blog/posts/making-the-most-of-the-arm-architecture-in-gcc-10#:~:text=out%20of%20line%20atomics> for more discussion.
//!
//! Currently we only support LL/SC, because LSE requires `getauxval` from libc in order to do runtime detection.
//! Use the `compiler-rt` intrinsics if you want LSE support.
//!
//! Ported from `aarch64/lse.S` in LLVM's compiler-rt.
//!
//! Generate functions for each of the following symbols:
@@ -24,7 +21,18 @@
//! We do something similar, but with macro arguments.
#![cfg_attr(feature = "c", allow(unused_macros))] // avoid putting the macros into a submodule
// We don't do runtime dispatch so we don't have to worry about the `__aarch64_have_lse_atomics` global ctor.
use core::sync::atomic::{AtomicU8, Ordering};
/// non-zero if the host supports LSE atomics.
static HAVE_LSE_ATOMICS: AtomicU8 = AtomicU8::new(0);
intrinsics! {
/// Call to enable LSE in outline atomic operations. The caller must verify
/// LSE operations are supported.
pub extern "C" fn __rust_enable_lse() {
HAVE_LSE_ATOMICS.store(1, Ordering::Relaxed);
}
}
/// Translate a byte size to a Rust type.
#[rustfmt::skip]
@@ -45,6 +53,7 @@ macro_rules! reg {
(2, $num:literal) => { concat!("w", $num) };
(4, $num:literal) => { concat!("w", $num) };
(8, $num:literal) => { concat!("x", $num) };
(16, $num:literal) => { concat!("x", $num) };
}
/// Given an atomic ordering, translate it to the acquire suffix for the lxdr aarch64 ASM instruction.
@@ -126,6 +135,41 @@ macro_rules! stxp {
};
}
// If supported, perform the requested LSE op and return, or fallthrough.
macro_rules! try_lse_op {
($op: literal, $ordering:ident, $bytes:tt, $($reg:literal,)* [ $mem:ident ] ) => {
concat!(
".arch_extension lse; ",
"adrp x16, {have_lse}; ",
"ldrb w16, [x16, :lo12:{have_lse}]; ",
"cbz w16, 8f; ",
// LSE_OP s(reg),* [$mem]
concat!(lse!($op, $ordering, $bytes), $( " ", reg!($bytes, $reg), ", " ,)* "[", stringify!($mem), "]; ",),
"ret; ",
"8:"
)
};
}
// Translate memory ordering to the LSE suffix
#[rustfmt::skip]
macro_rules! lse_mem_sfx {
(Relaxed) => { "" };
(Acquire) => { "a" };
(Release) => { "l" };
(AcqRel) => { "al" };
}
// Generate the aarch64 LSE operation for memory ordering and width
macro_rules! lse {
($op:literal, $order:ident, 16) => {
concat!($op, "p", lse_mem_sfx!($order))
};
($op:literal, $order:ident, $bytes:tt) => {
concat!($op, lse_mem_sfx!($order), size!($bytes))
};
}
/// See <https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicI8.html#method.compare_and_swap>.
macro_rules! compare_and_swap {
($ordering:ident, $bytes:tt, $name:ident) => {
@@ -137,7 +181,9 @@ macro_rules! compare_and_swap {
) -> int_ty!($bytes) {
// We can't use `AtomicI8::compare_and_swap`; we *are* compare_and_swap.
core::arch::naked_asm! {
// UXT s(tmp0), s(0)
// CAS s(0), s(1), [x2]; if LSE supported.
try_lse_op!("cas", $ordering, $bytes, 0, 1, [x2]),
// UXT s(tmp0), s(0)
concat!(uxt!($bytes), " ", reg!($bytes, 16), ", ", reg!($bytes, 0)),
"0:",
// LDXR s(0), [x2]
@@ -150,6 +196,7 @@ macro_rules! compare_and_swap {
"cbnz w17, 0b",
"1:",
"ret",
have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS,
}
}
}
@@ -166,6 +213,8 @@ macro_rules! compare_and_swap_i128 {
expected: i128, desired: i128, ptr: *mut i128
) -> i128 {
core::arch::naked_asm! {
// CASP x0, x1, x2, x3, [x4]; if LSE supported.
try_lse_op!("cas", $ordering, 16, 0, 1, 2, 3, [x4]),
"mov x16, x0",
"mov x17, x1",
"0:",
@@ -179,6 +228,7 @@ macro_rules! compare_and_swap_i128 {
"cbnz w15, 0b",
"1:",
"ret",
have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS,
}
}
}
@@ -195,6 +245,8 @@ macro_rules! swap {
left: int_ty!($bytes), right_ptr: *mut int_ty!($bytes)
) -> int_ty!($bytes) {
core::arch::naked_asm! {
// SWP s(0), s(0), [x1]; if LSE supported.
try_lse_op!("swp", $ordering, $bytes, 0, 0, [x1]),
// mov s(tmp0), s(0)
concat!("mov ", reg!($bytes, 16), ", ", reg!($bytes, 0)),
"0:",
@@ -204,6 +256,7 @@ macro_rules! swap {
concat!(stxr!($ordering, $bytes), " w17, ", reg!($bytes, 16), ", [x1]"),
"cbnz w17, 0b",
"ret",
have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS,
}
}
}
@@ -212,7 +265,7 @@ macro_rules! swap {
/// See (e.g.) <https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicI8.html#method.fetch_add>.
macro_rules! fetch_op {
($ordering:ident, $bytes:tt, $name:ident, $op:literal) => {
($ordering:ident, $bytes:tt, $name:ident, $op:literal, $lse_op:literal) => {
intrinsics! {
#[maybe_use_optimized_c_shim]
#[unsafe(naked)]
@@ -220,6 +273,8 @@ macro_rules! fetch_op {
val: int_ty!($bytes), ptr: *mut int_ty!($bytes)
) -> int_ty!($bytes) {
core::arch::naked_asm! {
// LSEOP s(0), s(0), [x1]; if LSE supported.
try_lse_op!($lse_op, $ordering, $bytes, 0, 0, [x1]),
// mov s(tmp0), s(0)
concat!("mov ", reg!($bytes, 16), ", ", reg!($bytes, 0)),
"0:",
@@ -231,6 +286,7 @@ macro_rules! fetch_op {
concat!(stxr!($ordering, $bytes), " w15, ", reg!($bytes, 17), ", [x1]"),
"cbnz w15, 0b",
"ret",
have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS,
}
}
}
@@ -240,25 +296,25 @@ macro_rules! fetch_op {
// We need a single macro to pass to `foreach_ldadd`.
macro_rules! add {
($ordering:ident, $bytes:tt, $name:ident) => {
fetch_op! { $ordering, $bytes, $name, "add" }
fetch_op! { $ordering, $bytes, $name, "add", "ldadd" }
};
}
macro_rules! and {
($ordering:ident, $bytes:tt, $name:ident) => {
fetch_op! { $ordering, $bytes, $name, "bic" }
fetch_op! { $ordering, $bytes, $name, "bic", "ldclr" }
};
}
macro_rules! xor {
($ordering:ident, $bytes:tt, $name:ident) => {
fetch_op! { $ordering, $bytes, $name, "eor" }
fetch_op! { $ordering, $bytes, $name, "eor", "ldeor" }
};
}
macro_rules! or {
($ordering:ident, $bytes:tt, $name:ident) => {
fetch_op! { $ordering, $bytes, $name, "orr" }
fetch_op! { $ordering, $bytes, $name, "orr", "ldset" }
};
}
@@ -1,5 +1,3 @@
#![cfg(not(feature = "no-asm"))]
// Interfaces used by naked trampolines.
// SAFETY: these are defined in compiler-builtins
unsafe extern "C" {
@@ -1,5 +1,3 @@
#![cfg(not(feature = "no-asm"))]
use core::arch::global_asm;
global_asm!(include_str!("hexagon/func_macro.s"), options(raw));
@@ -60,7 +60,7 @@
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
pub mod aarch64;
#[cfg(all(target_arch = "aarch64", target_os = "linux", not(feature = "no-asm"),))]
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
pub mod aarch64_linux;
#[cfg(all(
@@ -44,8 +44,6 @@
#![cfg(not(feature = "mangled-names"))]
// Windows and Cygwin already has builtins to do this.
#![cfg(not(any(windows, target_os = "cygwin")))]
// All these builtins require assembly
#![cfg(not(feature = "no-asm"))]
// We only define stack probing for these architectures today.
#![cfg(any(target_arch = "x86_64", target_arch = "x86"))]
@@ -9,10 +9,7 @@
intrinsics! {
#[unsafe(naked)]
#[cfg(all(
any(all(windows, target_env = "gnu"), target_os = "uefi"),
not(feature = "no-asm")
))]
#[cfg(any(all(windows, target_env = "gnu"), target_os = "uefi"))]
pub unsafe extern "custom" fn __chkstk() {
core::arch::naked_asm!(
"jmp {}", // Jump to __alloca since fallthrough may be unreliable"
@@ -21,10 +18,7 @@
}
#[unsafe(naked)]
#[cfg(all(
any(all(windows, target_env = "gnu"), target_os = "uefi"),
not(feature = "no-asm")
))]
#[cfg(any(all(windows, target_env = "gnu"), target_os = "uefi"))]
pub unsafe extern "custom" fn _alloca() {
// __chkstk and _alloca are the same function
core::arch::naked_asm!(
@@ -9,14 +9,7 @@
intrinsics! {
#[unsafe(naked)]
#[cfg(all(
any(
all(windows, target_env = "gnu"),
target_os = "cygwin",
target_os = "uefi"
),
not(feature = "no-asm")
))]
#[cfg(any(all(windows, target_env = "gnu"), target_os = "cygwin", target_os = "uefi"))]
pub unsafe extern "custom" fn ___chkstk_ms() {
core::arch::naked_asm!(
"push %rcx",
@@ -40,8 +40,6 @@ mod tests {
) => {
// Run a simple check to ensure we can link and call the function without crashing.
#[test]
// FIXME(#309): LE PPC crashes calling some musl functions
#[cfg_attr(all(target_arch = "powerpc64", target_endian = "little"), ignore)]
fn $name() {
<fn($($aty),+) -> $rty>::check(super::$name);
}
@@ -5,8 +5,7 @@ edition = "2024"
publish = false
[dependencies]
# FIXME: used as a git dependency since the latest release does not support wasm
object = { git = "https://github.com/gimli-rs/object.git", rev = "013fac75da56a684377af4151b8164b78c1790e0" }
object = "0.37.1"
serde_json = "1.0.140"
[features]
@@ -271,18 +271,6 @@ fn check_int<I: Int>(input: (f32,), actual: I, expected: I, ctx: &CheckCtx) -> C
impl MaybeOverride<(f64,)> for SpecialCase {
fn check_float<F: Float>(input: (f64,), actual: F, expected: F, ctx: &CheckCtx) -> CheckAction {
if cfg!(x86_no_sse)
&& ctx.base_name == BaseName::Ceil
&& ctx.basis == CheckBasis::Musl
&& input.0 < 0.0
&& input.0 > -1.0
&& expected == F::ZERO
&& actual == F::ZERO
{
// musl returns -0.0, we return +0.0
return XFAIL("i586 ceil signed zero");
}
if cfg!(x86_no_sse)
&& (ctx.base_name == BaseName::Rint || ctx.base_name == BaseName::Roundeven)
&& (expected - actual).abs() <= F::ONE
@@ -292,16 +280,6 @@ fn check_float<F: Float>(input: (f64,), actual: F, expected: F, ctx: &CheckCtx)
return XFAIL("i586 rint rounding mode");
}
if cfg!(x86_no_sse)
&& (ctx.fn_ident == Identifier::Ceil || ctx.fn_ident == Identifier::Floor)
&& expected.eq_repr(F::NEG_ZERO)
&& actual.eq_repr(F::ZERO)
{
// FIXME: the x87 implementations do not keep the distinction between -0.0 and 0.0.
// See https://github.com/rust-lang/libm/pull/404#issuecomment-2572399955
return XFAIL("i586 ceil/floor signed zero");
}
if cfg!(x86_no_sse)
&& (ctx.fn_ident == Identifier::Exp10 || ctx.fn_ident == Identifier::Exp2)
{
+6 -24
View File
@@ -1,9 +1,9 @@
// Configuration shared with both libm and libm-test
use std::env;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::{env, str};
#[derive(Debug)]
#[allow(dead_code)]
pub struct Config {
pub manifest_dir: PathBuf,
@@ -33,26 +33,6 @@ pub fn from_env() -> Self {
.map(|s| s.to_lowercase().replace("_", "-"))
.collect();
// Query rustc for options that Cargo does not provide env for. The bootstrap hack is used
// to get consistent output regardless of channel (`f16`/`f128` config options are hidden
// on stable otherwise).
let mut cmd = Command::new(env::var("RUSTC").unwrap());
cmd.args(["--print=cfg", "--target", &target_triple])
.env("RUSTC_BOOTSTRAP", "1")
.stderr(Stdio::inherit());
let out = cmd
.output()
.unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
let rustc_cfg = str::from_utf8(&out.stdout).unwrap();
// If we couldn't query `rustc` (e.g. a custom JSON target was used), make the safe
// choice and leave `f16` and `f128` disabled.
let rustc_output_ok = out.status.success();
let reliable_f128 =
rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f128");
let reliable_f16 =
rustc_output_ok && rustc_cfg.lines().any(|l| l == "target_has_reliable_f16");
Self {
target_triple,
manifest_dir: PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()),
@@ -66,8 +46,10 @@ pub fn from_env() -> Self {
target_string: env::var("TARGET").unwrap(),
target_vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
target_features,
reliable_f128,
reliable_f16,
// Note that these are unstable options, so only show up with the nightly compiler or
// with `RUSTC_BOOTSTRAP=1` (which is required to use the types anyway).
reliable_f128: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F128").is_some(),
reliable_f16: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F16").is_some(),
}
}
}
@@ -59,7 +59,7 @@ fn r(z: f64) -> f64 {
/// Computes the inverse cosine (arc cosine) of the input value.
/// Arguments must be in the range -1 to 1.
/// Returns values in radians, in the range of 0 to pi.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn acos(x: f64) -> f64 {
let x1p_120f = f64::from_bits(0x3870000000000000); // 0x1p-120 === 2 ^ -120
let z: f64;
@@ -33,7 +33,7 @@ fn r(z: f32) -> f32 {
/// Computes the inverse cosine (arc cosine) of the input value.
/// Arguments must be in the range -1 to 1.
/// Returns values in radians, in the range of 0 to pi.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn acosf(x: f32) -> f32 {
let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120)
@@ -7,7 +7,7 @@
/// Calculates the inverse hyperbolic cosine of `x`.
/// Is defined as `log(x + sqrt(x*x-1))`.
/// `x` must be a number greater than or equal to 1.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn acosh(x: f64) -> f64 {
let u = x.to_bits();
let e = ((u >> 52) as usize) & 0x7ff;
@@ -7,7 +7,7 @@
/// Calculates the inverse hyperbolic cosine of `x`.
/// Is defined as `log(x + sqrt(x*x-1))`.
/// `x` must be a number greater than or equal to 1.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn acoshf(x: f32) -> f32 {
let u = x.to_bits();
let a = u & 0x7fffffff;
@@ -1,37 +1,62 @@
//! Architecture-specific support for x86-32 without SSE2
//!
//! We use an alternative implementation on x86, because the
//! main implementation fails with the x87 FPU used by
//! debian i386, probably due to excess precision issues.
//!
//! See https://github.com/rust-lang/compiler-builtins/pull/976 for discussion on why these
//! functions are implemented in this way.
use super::super::fabs;
/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn ceil(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated < x {
return truncated + 1.0;
} else {
return truncated;
}
} else {
return x;
pub fn ceil(mut x: f64) -> f64 {
unsafe {
core::arch::asm!(
"fld qword ptr [{x}]",
// Save the FPU control word, using `x` as scratch space.
"fstcw [{x}]",
// Set rounding control to 0b10 (+∞).
"mov word ptr [{x} + 2], 0x0b7f",
"fldcw [{x} + 2]",
// Round.
"frndint",
// Restore FPU control word.
"fldcw [{x}]",
// Save rounded value to memory.
"fstp qword ptr [{x}]",
x = in(reg) &mut x,
// All the x87 FPU stack is used, all registers must be clobbered
out("st(0)") _, out("st(1)") _,
out("st(2)") _, out("st(3)") _,
out("st(4)") _, out("st(5)") _,
out("st(6)") _, out("st(7)") _,
options(nostack),
);
}
x
}
/// Use an alternative implementation on x86, because the
/// main implementation fails with the x87 FPU used by
/// debian i386, probably due to excess precision issues.
/// Basic implementation taken from https://github.com/rust-lang/libm/issues/219.
pub fn floor(x: f64) -> f64 {
if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
let truncated = x as i64 as f64;
if truncated > x {
return truncated - 1.0;
} else {
return truncated;
}
} else {
return x;
pub fn floor(mut x: f64) -> f64 {
unsafe {
core::arch::asm!(
"fld qword ptr [{x}]",
// Save the FPU control word, using `x` as scratch space.
"fstcw [{x}]",
// Set rounding control to 0b01 (-∞).
"mov word ptr [{x} + 2], 0x077f",
"fldcw [{x} + 2]",
// Round.
"frndint",
// Restore FPU control word.
"fldcw [{x}]",
// Save rounded value to memory.
"fstp qword ptr [{x}]",
x = in(reg) &mut x,
// All the x87 FPU stack is used, all registers must be clobbered
out("st(0)") _, out("st(1)") _,
out("st(2)") _, out("st(3)") _,
out("st(4)") _, out("st(5)") _,
out("st(6)") _, out("st(7)") _,
options(nostack),
);
}
x
}
@@ -66,7 +66,7 @@ fn comp_r(z: f64) -> f64 {
/// Computes the inverse sine (arc sine) of the argument `x`.
/// Arguments to asin must be in the range -1 to 1.
/// Returns values in radians, in the range of -pi/2 to pi/2.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn asin(mut x: f64) -> f64 {
let z: f64;
let r: f64;
@@ -35,7 +35,7 @@ fn r(z: f32) -> f32 {
/// Computes the inverse sine (arc sine) of the argument `x`.
/// Arguments to asin must be in the range -1 to 1.
/// Returns values in radians, in the range of -pi/2 to pi/2.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn asinf(mut x: f32) -> f32 {
let x1p_120 = f64::from_bits(0x3870000000000000); // 0x1p-120 === 2 ^ (-120)
@@ -7,7 +7,7 @@
///
/// Calculates the inverse hyperbolic sine of `x`.
/// Is defined as `sgn(x)*log(|x|+sqrt(x*x+1))`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn asinh(mut x: f64) -> f64 {
let mut u = x.to_bits();
let e = ((u >> 52) as usize) & 0x7ff;
@@ -7,7 +7,7 @@
///
/// Calculates the inverse hyperbolic sine of `x`.
/// Is defined as `sgn(x)*log(|x|+sqrt(x*x+1))`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn asinhf(mut x: f32) -> f32 {
let u = x.to_bits();
let i = u & 0x7fffffff;
@@ -65,7 +65,7 @@
///
/// Computes the inverse tangent (arc tangent) of the input value.
/// Returns a value in radians, in the range of -pi/2 to pi/2.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atan(x: f64) -> f64 {
let mut x = x;
let mut ix = (x.to_bits() >> 32) as u32;
@@ -47,7 +47,7 @@
/// Computes the inverse tangent (arc tangent) of `y/x`.
/// Produces the correct result even for angles near pi/2 or -pi/2 (that is, when `x` is near 0).
/// Returns a value in radians, in the range of -pi to pi.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atan2(y: f64, x: f64) -> f64 {
if x.is_nan() || y.is_nan() {
return x + y;
@@ -23,7 +23,7 @@
/// Computes the inverse tangent (arc tangent) of `y/x`.
/// Produces the correct result even for angles near pi/2 or -pi/2 (that is, when `x` is near 0).
/// Returns a value in radians, in the range of -pi to pi.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atan2f(y: f32, x: f32) -> f32 {
if x.is_nan() || y.is_nan() {
return x + y;
@@ -41,7 +41,7 @@
///
/// Computes the inverse tangent (arc tangent) of the input value.
/// Returns a value in radians, in the range of -pi/2 to pi/2.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atanf(mut x: f32) -> f32 {
let x1p_120 = f32::from_bits(0x03800000); // 0x1p-120 === 2 ^ (-120)
@@ -5,7 +5,7 @@
///
/// Calculates the inverse hyperbolic tangent of `x`.
/// Is defined as `log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atanh(x: f64) -> f64 {
let u = x.to_bits();
let e = ((u >> 52) as usize) & 0x7ff;
@@ -5,7 +5,7 @@
///
/// Calculates the inverse hyperbolic tangent of `x`.
/// Is defined as `log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn atanhf(mut x: f32) -> f32 {
let mut u = x.to_bits();
let sign = (u >> 31) != 0;
@@ -8,7 +8,7 @@
use super::support::{FpResult, Round, cold_path};
/// Compute the cube root of the argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn cbrt(x: f64) -> f64 {
cbrt_round(x, Round::Nearest).val
}
@@ -25,7 +25,7 @@
/// Cube root (f32)
///
/// Computes the cube root of the argument.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn cbrtf(x: f32) -> f32 {
let x1p24 = f32::from_bits(0x4b800000); // 0x1p24f === 2 ^ 24
@@ -2,7 +2,7 @@
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn ceilf16(x: f16) -> f16 {
super::generic::ceil(x)
}
@@ -10,7 +10,7 @@ pub fn ceilf16(x: f16) -> f16 {
/// Ceil (f32)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn ceilf(x: f32) -> f32 {
select_implementation! {
name: ceilf,
@@ -24,7 +24,7 @@ pub fn ceilf(x: f32) -> f32 {
/// Ceil (f64)
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn ceil(x: f64) -> f64 {
select_implementation! {
name: ceil,
@@ -40,7 +40,7 @@ pub fn ceil(x: f64) -> f64 {
///
/// Finds the nearest integer greater than or equal to `x`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn ceilf128(x: f128) -> f128 {
super::generic::ceil(x)
}
@@ -3,7 +3,7 @@
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn copysignf16(x: f16, y: f16) -> f16 {
super::generic::copysign(x, y)
}
@@ -12,7 +12,7 @@ pub fn copysignf16(x: f16, y: f16) -> f16 {
///
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn copysignf(x: f32, y: f32) -> f32 {
super::generic::copysign(x, y)
}
@@ -21,7 +21,7 @@ pub fn copysignf(x: f32, y: f32) -> f32 {
///
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn copysign(x: f64, y: f64) -> f64 {
super::generic::copysign(x, y)
}
@@ -31,7 +31,7 @@ pub fn copysign(x: f64, y: f64) -> f64 {
/// Constructs a number with the magnitude (absolute value) of its
/// first argument, `x`, and the sign of its second argument, `y`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn copysignf128(x: f128, y: f128) -> f128 {
super::generic::copysign(x, y)
}
@@ -45,7 +45,7 @@
/// The cosine of `x` (f64).
///
/// `x` is specified in radians.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn cos(x: f64) -> f64 {
let ix = (f64::to_bits(x) >> 32) as u32 & 0x7fffffff;
@@ -27,7 +27,7 @@
/// The cosine of `x` (f32).
///
/// `x` is specified in radians.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn cosf(x: f32) -> f32 {
let x64 = x as f64;
@@ -5,7 +5,7 @@
/// Computes the hyperbolic cosine of the argument x.
/// Is defined as `(exp(x) + exp(-x))/2`
/// Angles are specified in radians.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn cosh(mut x: f64) -> f64 {
/* |x| */
let mut ix = x.to_bits();
@@ -5,7 +5,7 @@
/// Computes the hyperbolic cosine of the argument x.
/// Is defined as `(exp(x) + exp(-x))/2`
/// Angles are specified in radians.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn coshf(mut x: f32) -> f32 {
let x1p120 = f32::from_bits(0x7b800000); // 0x1p120f === 2 ^ 120
@@ -219,7 +219,7 @@ fn erfc2(ix: u32, mut x: f64) -> f64 {
/// Calculates an approximation to the “error function”, which estimates
/// the probability that an observation will fall within x standard
/// deviations of the mean (assuming a normal distribution).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn erf(x: f64) -> f64 {
let r: f64;
let s: f64;
@@ -130,7 +130,7 @@ fn erfc2(mut ix: u32, mut x: f32) -> f32 {
/// Calculates an approximation to the “error function”, which estimates
/// the probability that an observation will fall within x standard
/// deviations of the mean (assuming a normal distribution).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn erff(x: f32) -> f32 {
let r: f32;
let s: f32;
@@ -81,7 +81,7 @@
///
/// Calculate the exponential of `x`, that is, *e* raised to the power `x`
/// (where *e* is the base of the natural system of logarithms, approximately 2.71828).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn exp(mut x: f64) -> f64 {
let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023
let x1p_149 = f64::from_bits(0x36a0000000000000); // 0x1p-149 === 2 ^ -149
@@ -7,7 +7,7 @@
];
/// Calculates 10 raised to the power of `x` (f64).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn exp10(x: f64) -> f64 {
let (mut y, n) = modf(x);
let u: u64 = n.to_bits();
@@ -7,7 +7,7 @@
];
/// Calculates 10 raised to the power of `x` (f32).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn exp10f(x: f32) -> f32 {
let (mut y, n) = modff(x);
let u = n.to_bits();
@@ -322,7 +322,7 @@
/// Exponential, base 2 (f64)
///
/// Calculate `2^x`, that is, 2 raised to the power `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn exp2(mut x: f64) -> f64 {
let redux = f64::from_bits(0x4338000000000000) / TBLSIZE as f64;
let p1 = f64::from_bits(0x3fe62e42fefa39ef);
@@ -73,7 +73,7 @@
/// Exponential, base 2 (f32)
///
/// Calculate `2^x`, that is, 2 raised to the power `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn exp2f(mut x: f32) -> f32 {
let redux = f32::from_bits(0x4b400000) / TBLSIZE as f32;
let p1 = f32::from_bits(0x3f317218);
@@ -30,7 +30,7 @@
///
/// Calculate the exponential of `x`, that is, *e* raised to the power `x`
/// (where *e* is the base of the natural system of logarithms, approximately 2.71828).
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn expf(mut x: f32) -> f32 {
let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127
let x1p_126 = f32::from_bits(0x800000); // 0x1p-126f === 2 ^ -126 /*original 0x1p-149f ??????????? */
@@ -30,7 +30,7 @@
/// system of logarithms, approximately 2.71828).
/// The result is accurate even for small values of `x`,
/// where using `exp(x)-1` would lose many significant digits.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn expm1(mut x: f64) -> f64 {
let hi: f64;
let lo: f64;
@@ -32,7 +32,7 @@
/// system of logarithms, approximately 2.71828).
/// The result is accurate even for small values of `x`,
/// where using `exp(x)-1` would lose many significant digits.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn expm1f(mut x: f32) -> f32 {
let x1p127 = f32::from_bits(0x7f000000); // 0x1p127f === 2 ^ 127
@@ -1,7 +1,7 @@
use super::{combine_words, exp};
/* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub(crate) fn expo2(x: f64) -> f64 {
/* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */
const K: i32 = 2043;
@@ -3,7 +3,7 @@
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fabsf16(x: f16) -> f16 {
super::generic::fabs(x)
}
@@ -12,7 +12,7 @@ pub fn fabsf16(x: f16) -> f16 {
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fabsf(x: f32) -> f32 {
select_implementation! {
name: fabsf,
@@ -27,7 +27,7 @@ pub fn fabsf(x: f32) -> f32 {
///
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fabs(x: f64) -> f64 {
select_implementation! {
name: fabs,
@@ -43,7 +43,7 @@ pub fn fabs(x: f64) -> f64 {
/// Calculates the absolute value (magnitude) of the argument `x`,
/// by direct manipulation of the bit representation of `x`.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fabsf128(x: f128) -> f128 {
super::generic::fabs(x)
}
@@ -7,7 +7,7 @@
///
/// A range error may occur.
#[cfg(f16_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fdimf16(x: f16, y: f16) -> f16 {
super::generic::fdim(x, y)
}
@@ -20,7 +20,7 @@ pub fn fdimf16(x: f16, y: f16) -> f16 {
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fdimf(x: f32, y: f32) -> f32 {
super::generic::fdim(x, y)
}
@@ -33,7 +33,7 @@ pub fn fdimf(x: f32, y: f32) -> f32 {
/// * NAN if either argument is NAN.
///
/// A range error may occur.
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fdim(x: f64, y: f64) -> f64 {
super::generic::fdim(x, y)
}
@@ -47,7 +47,7 @@ pub fn fdim(x: f64, y: f64) -> f64 {
///
/// A range error may occur.
#[cfg(f128_enabled)]
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
#[cfg_attr(assert_no_panic, no_panic::no_panic)]
pub fn fdimf128(x: f128, y: f128) -> f128 {
super::generic::fdim(x, y)
}

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