Merge ref '8401398e1f' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref:8401398e1fFiltered ref: f9e99a8e85fa360f0e820dc75d46cb4583b4300d Upstream diff:73e6c9ebd9...8401398e1fThis merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
485ea04b6d
2488 changed files with 27158 additions and 17875 deletions
2
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
2
.github/ISSUE_TEMPLATE/tracking_issue.md
vendored
|
|
@ -50,7 +50,7 @@ for larger features an implementation could be broken up into multiple PRs.
|
|||
[stabilization-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr
|
||||
[doc-guide]: https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#documentation-prs
|
||||
[nightly-style-procedure]: https://github.com/rust-lang/style-team/blob/main/nightly-style-procedure.md
|
||||
[Style Guide]: https://github.com/rust-lang/rust/tree/master/src/doc/style-guide
|
||||
[Style Guide]: https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide
|
||||
|
||||
### Unresolved Questions
|
||||
<!--
|
||||
|
|
|
|||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -323,7 +323,7 @@ jobs:
|
|||
# If a some dependent job has failed, this exits with 1.
|
||||
- name: calculate the correct exit status
|
||||
run: jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
|
||||
# Publish the toolstate if an auto build succeeds (just before push to master)
|
||||
# Publish the toolstate if an auto build succeeds (just before push to the default branch)
|
||||
- name: publish toolstate
|
||||
run: src/ci/publish_toolstate.sh
|
||||
shell: bash
|
||||
|
|
|
|||
2
.github/workflows/post-merge.yml
vendored
2
.github/workflows/post-merge.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
# Workflow that runs after a merge to master, analyses changes in test executions
|
||||
# Workflow that runs after a merge to the default branch, analyses changes in test executions
|
||||
# and posts the result to the merged PR.
|
||||
|
||||
name: Post merge analysis
|
||||
|
|
|
|||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -90,6 +90,10 @@ node_modules
|
|||
## Rustdoc GUI tests
|
||||
tests/rustdoc-gui/src/**.lock
|
||||
|
||||
## Test dashboard
|
||||
.citool-cache/
|
||||
test-dashboard/
|
||||
|
||||
## direnv
|
||||
/.envrc
|
||||
/.direnv/
|
||||
|
|
|
|||
21
.mailmap
21
.mailmap
|
|
@ -9,7 +9,7 @@ Aaron Todd <github@opprobrio.us>
|
|||
Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com>
|
||||
Abhijeet Bhagat <abhijeet.bhagat@gmx.com>
|
||||
Abroskin Alexander <arkweid@evilmartians.com>
|
||||
Adolfo Ochagavía <aochagavia92@gmail.com>
|
||||
Adolfo Ochagavía <aochagavia92@gmail.com> <github@adolfo.ochagavia.xyz>
|
||||
Adrian Heine né Lang <mail@adrianheine.de>
|
||||
Adrien Tétar <adri-from-59@hotmail.fr>
|
||||
Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
|
||||
|
|
@ -36,6 +36,7 @@ Amanda Stjerna <mail@amandastjerna.se> <albin.stjerna@gmail.com>
|
|||
Amanda Stjerna <mail@amandastjerna.se> <amanda.stjerna@it.uu.se>
|
||||
Amanieu d'Antras <amanieu@gmail.com> <amanieu.dantras@huawei.com>
|
||||
Amos Onn <amosonn@gmail.com>
|
||||
Amos Wenger <amoswenger@gmail.com> <fasterthanlime@users.noreply.github.com>
|
||||
Ana-Maria Mihalache <mihalacheana.maria@yahoo.com>
|
||||
Anatoly Ikorsky <aikorsky@gmail.com>
|
||||
Andre Bogus <bogusandre@gmail.com>
|
||||
|
|
@ -138,7 +139,6 @@ Christian Poveda <git@pvdrz.com> <31802960+christianpoveda@users.noreply.github.
|
|||
Christian Poveda <git@pvdrz.com> <christianpoveda@uhura.edef.eu>
|
||||
Christian Vallentin <vallentinsource@gmail.com>
|
||||
Christoffer Buchholz <chris@chrisbuchholz.me>
|
||||
Christopher Durham <cad97@cad97.com>
|
||||
Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
|
||||
Clement Miao <clementmiao@gmail.com>
|
||||
Clément Renault <renault.cle@gmail.com>
|
||||
|
|
@ -147,6 +147,7 @@ Clinton Ryan <clint.ryan3@gmail.com>
|
|||
Taylor Cramer <cramertaylorj@gmail.com> <cramertj@google.com>
|
||||
ember arlynx <ember@lunar.town> <corey@octayn.net>
|
||||
Crazycolorz5 <Crazycolorz5@gmail.com>
|
||||
Crystal Durham <cad97@cad97.com>
|
||||
csmoe <35686186+csmoe@users.noreply.github.com>
|
||||
Cyryl Płotnicki <cyplo@cyplo.net>
|
||||
Damien Schoof <damien.schoof@gmail.com>
|
||||
|
|
@ -276,7 +277,8 @@ Irina Popa <irinagpopa@gmail.com>
|
|||
Ivan Ivaschenko <defuz.net@gmail.com>
|
||||
ivan tkachenko <me@ratijas.tk>
|
||||
J. J. Weber <jjweber@gmail.com>
|
||||
Jack Huey <jack.huey@umassmed.edu> <jackh726@gmail.com>
|
||||
Jack Huey <jackh726@gmail.com> <jack.huey@umassmed.edu>
|
||||
Jack Huey <jackh726@gmail.com> <31162821+jackh726@users.noreply.github.com>
|
||||
Jacob <jacob.macritchie@gmail.com>
|
||||
Jacob Hoffman-Andrews <rust@hoffman-andrews.com> <github@hoffman-andrews.com>
|
||||
Jacob Greenfield <xales@naveria.com>
|
||||
|
|
@ -292,6 +294,8 @@ Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com>
|
|||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <ja.wieczorek@student.uw.edu.pl>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <software@jacobadam.net>
|
||||
Jakub Beránek <berykubik@gmail.com> <jakub.beranek@vsb.cz>
|
||||
James [Undefined] <tpzker@thepuzzlemaker.info>
|
||||
James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com>
|
||||
|
|
@ -303,6 +307,7 @@ Jamie Hill-Daniel <jamie@hill-daniel.co.uk> <clubby789@gmail.com>
|
|||
Jana Dönszelmann <jana@donsz.nl>
|
||||
Jana Dönszelmann <jana@donsz.nl> <jonathan@donsz.nl>
|
||||
Jana Dönszelmann <jana@donsz.nl> <jonabent@gmail.com>
|
||||
Jane Lusby <jlusby42@gmail.com> <jlusby@yaah.dev>
|
||||
Jan-Erik Rediger <janerik@fnordig.de> <badboy@archlinux.us>
|
||||
Jaro Fietz <jaro.fietz@gmx.de>
|
||||
Jason Fager <jfager@gmail.com>
|
||||
|
|
@ -313,6 +318,7 @@ Jason Toffaletti <toffaletti@gmail.com> Jason Toffaletti <jason@topsy.com>
|
|||
Jauhien Piatlicki <jauhien@gentoo.org> Jauhien Piatlicki <jpiatlicki@zertisa.com>
|
||||
Jay True <glacjay@gmail.com>
|
||||
Jeremy Letang <letang.jeremy@gmail.com>
|
||||
Jeremy Soller <jackpot51@gmail.com> <jeremy@system76.com>
|
||||
Jeremy Sorensen <jeremy.a.sorensen@gmail.com>
|
||||
Jeremy Stucki <dev@jeremystucki.ch> <stucki.jeremy@gmail.com>
|
||||
Jeremy Stucki <dev@jeremystucki.ch> <jeremy@myelin.ch>
|
||||
|
|
@ -336,6 +342,7 @@ John Kåre Alsaker <john.kare.alsaker@gmail.com>
|
|||
John Kåre Alsaker <john.kare.alsaker@gmail.com> <zoxc32@gmail.com>
|
||||
John Talling <inrustwetrust@users.noreply.github.com>
|
||||
John Van Enk <vanenkj@gmail.com>
|
||||
Jon Gjengset <jon@thesquareplanet.com> <jongje@amazon.com>
|
||||
Jonas Tepe <jonasprogrammer@gmail.com>
|
||||
Jonathan Bailey <jbailey@mozilla.com> <jbailey@jbailey-20809.local>
|
||||
Jonathan Chan Kwan Yin <sofe2038@gmail.com>
|
||||
|
|
@ -424,7 +431,7 @@ Malo Jaffré <jaffre.malo@gmail.com>
|
|||
Manish Goregaokar <manishsmail@gmail.com>
|
||||
Mara Bos <m-ou.se@m-ou.se>
|
||||
Marcell Pardavi <marcell.pardavi@gmail.com>
|
||||
Marco Ieni <11428655+MarcoIeni@users.noreply.github.com>
|
||||
Marco Ieni <marcoieni@rustfoundation.org> <11428655+MarcoIeni@users.noreply.github.com>
|
||||
Marcus Klaas de Vries <mail@marcusklaas.nl>
|
||||
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew>
|
||||
Marijn Schouten <mhkbst@gmail.com> <hkBst@users.noreply.github.com>
|
||||
|
|
@ -531,6 +538,7 @@ Oliver Scherer <oli-obk@users.noreply.github.com> <oliver.schneider@kit.edu>
|
|||
Oliver Scherer <oli-obk@users.noreply.github.com> <obk8176014uqher834@olio-obk.de>
|
||||
Oliver Scherer <oli-obk@users.noreply.github.com> <rustc-contact@oli-obk.de>
|
||||
Oliver Scherer <oli-obk@users.noreply.github.com>
|
||||
Onur Özkan <onurozkan.dev@outlook.com> <contact@onurozkan.dev>
|
||||
Onur Özkan <onurozkan.dev@outlook.com> <work@onurozkan.dev>
|
||||
Onur Özkan <onurozkan.dev@outlook.com>
|
||||
Ömer Sinan Ağacan <omeragacan@gmail.com>
|
||||
|
|
@ -591,6 +599,7 @@ Rusty Blitzerr <rusty.blitzerr@gmail.com>
|
|||
RustyYato <krishna.sd.2012@gmail.com>
|
||||
Ruud van Asseldonk <dev@veniogames.com> Ruud van Asseldonk <ruuda@google.com>
|
||||
Ryan Leung <rleungx@gmail.com>
|
||||
Ryan Levick <me@ryanlevick.com> <rylev@users.noreply.github.com>
|
||||
Ryan Scheel <ryan.havvy@gmail.com>
|
||||
Ryan Sullivant <rsulli55@gmail.com>
|
||||
Ryan Wiedemann <Ryan1729@gmail.com>
|
||||
|
|
@ -686,6 +695,8 @@ Weihang Lo <me@weihanglo.tw>
|
|||
Weihang Lo <me@weihanglo.tw> <weihanglo@users.noreply.github.com>
|
||||
Wesley Wiser <wwiser@gmail.com> <wesleywiser@microsoft.com>
|
||||
whitequark <whitequark@whitequark.org>
|
||||
Will Crichton <crichton.will@gmail.com> <wcrichto@stanford.edu>
|
||||
Will Crichton <crichton.will@gmail.com> <wcrichto@cs.stanford.edu>
|
||||
William Ting <io@williamting.com> <william.h.ting@gmail.com>
|
||||
Wim Looman <wim@nemo157.com> <rust-lang@nemo157.com>
|
||||
Wim Looman <wim@nemo157.com> <git@nemo157.com>
|
||||
|
|
@ -695,6 +706,8 @@ Xinye Tao <xy.tao@outlook.com>
|
|||
Xuefeng Wu <benewu@gmail.com> Xuefeng Wu <xfwu@thoughtworks.com>
|
||||
Xuefeng Wu <benewu@gmail.com> XuefengWu <benewu@gmail.com>
|
||||
York Xiang <bombless@126.com>
|
||||
Yoshua Wuyts <yoshuawuyts@gmail.com> <yoshuawuyts+github@gmail.com>
|
||||
Yoshua Wuyts <yoshuawuyts@gmail.com> <2467194+yoshuawuyts@users.noreply.github.com>
|
||||
Yotam Ofek <yotam.ofek@gmail.com> <yotamofek@microsoft.com>
|
||||
Youngsoo Son <ysson83@gmail.com> <ysoo.son@samsung.com>
|
||||
Youngsuk Kim <joseph942010@gmail.com>
|
||||
|
|
|
|||
10
Cargo.lock
10
Cargo.lock
|
|
@ -80,9 +80,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.12.7"
|
||||
version = "0.12.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47224528f74de27d1d06aad6a5dda4f865b6ebe2e56c538943d746a7270cb67e"
|
||||
checksum = "025c7edcdffa4ccc5c0905f472a0ae3759378cfbef88ef518a3575e19ae3aebd"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"unicode-width 0.2.2",
|
||||
|
|
@ -2334,9 +2334,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
|
|
@ -3766,7 +3766,7 @@ dependencies = [
|
|||
name = "rustc_errors"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.12.7",
|
||||
"annotate-snippets 0.12.8",
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"derive_setters",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
Version 1.91.1 (2025-11-10)
|
||||
===========================
|
||||
|
||||
<a id="1.91.1"></a>
|
||||
|
||||
- [Enable file locking support in illumos](https://github.com/rust-lang/rust/pull/148322). This fixes Cargo not locking the build directory on illumos.
|
||||
- [Fix `wasm_import_module` attribute cross-crate](https://github.com/rust-lang/rust/pull/148363). This fixes linker errors on WASM targets.
|
||||
|
||||
Version 1.91.0 (2025-10-30)
|
||||
==========================
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,20 @@ pub enum CanonAbi {
|
|||
X86(X86Call),
|
||||
}
|
||||
|
||||
impl CanonAbi {
|
||||
pub fn is_rustic_abi(self) -> bool {
|
||||
match self {
|
||||
CanonAbi::Rust | CanonAbi::RustCold => true,
|
||||
CanonAbi::C
|
||||
| CanonAbi::Custom
|
||||
| CanonAbi::Arm(_)
|
||||
| CanonAbi::GpuKernel
|
||||
| CanonAbi::Interrupt(_)
|
||||
| CanonAbi::X86(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CanonAbi {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// convert to the ExternAbi that *shares a string* with this CanonAbi.
|
||||
|
|
|
|||
|
|
@ -812,7 +812,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
let (max, min) = largest_niche
|
||||
// We might have no inhabited variants, so pretend there's at least one.
|
||||
.unwrap_or((0, 0));
|
||||
let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max);
|
||||
let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::discr_range_of_repr(tcx, ty, &repr, min, max);
|
||||
|
||||
let mut align = dl.aggregate_align;
|
||||
let mut max_repr_align = repr.align;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,8 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
|
|||
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
|
||||
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
|
||||
fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
|
||||
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
|
||||
fn is_pass_indirectly_in_non_rustic_abis_flag_set(this: TyAndLayout<'a, Self>) -> bool;
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
|
|
@ -269,6 +271,30 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||
Ty::is_transparent(self)
|
||||
}
|
||||
|
||||
/// If this method returns `true`, then this type should always have a `PassMode` of
|
||||
/// `Indirect { on_stack: false, .. }` when being used as the argument type of a function with a
|
||||
/// non-Rustic ABI (this is true for structs annotated with the
|
||||
/// `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute).
|
||||
///
|
||||
/// This is used to replicate some of the behaviour of C array-to-pointer decay; however unlike
|
||||
/// C any changes the caller makes to the passed value will not be reflected in the callee, so
|
||||
/// the attribute is only useful for types where observing the value in the caller after the
|
||||
/// function call isn't allowed (a.k.a. `va_list`).
|
||||
///
|
||||
/// This function handles transparent types automatically.
|
||||
pub fn pass_indirectly_in_non_rustic_abis<C>(mut self, cx: &C) -> bool
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
while self.is_transparent()
|
||||
&& let Some((_, field)) = self.non_1zst_field(cx)
|
||||
{
|
||||
self = field;
|
||||
}
|
||||
|
||||
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self)
|
||||
}
|
||||
|
||||
/// Finds the one field that is not a 1-ZST.
|
||||
/// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
|
||||
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
// tidy-alphabetical-start
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
#![cfg_attr(feature = "nightly", doc(rust_logo))]
|
||||
#![cfg_attr(feature = "nightly", feature(assert_matches))]
|
||||
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
|
||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
@ -88,14 +86,17 @@ bitflags! {
|
|||
const IS_C = 1 << 0;
|
||||
const IS_SIMD = 1 << 1;
|
||||
const IS_TRANSPARENT = 1 << 2;
|
||||
// Internal only for now. If true, don't reorder fields.
|
||||
// On its own it does not prevent ABI optimizations.
|
||||
/// Internal only for now. If true, don't reorder fields.
|
||||
/// On its own it does not prevent ABI optimizations.
|
||||
const IS_LINEAR = 1 << 3;
|
||||
// If true, the type's crate has opted into layout randomization.
|
||||
// Other flags can still inhibit reordering and thus randomization.
|
||||
// The seed stored in `ReprOptions.field_shuffle_seed`.
|
||||
/// If true, the type's crate has opted into layout randomization.
|
||||
/// Other flags can still inhibit reordering and thus randomization.
|
||||
/// The seed stored in `ReprOptions.field_shuffle_seed`.
|
||||
const RANDOMIZE_LAYOUT = 1 << 4;
|
||||
// Any of these flags being set prevent field reordering optimisation.
|
||||
/// If true, the type is always passed indirectly by non-Rustic ABIs.
|
||||
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
|
||||
const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
|
||||
/// Any of these flags being set prevent field reordering optimisation.
|
||||
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
|
||||
| ReprFlags::IS_SIMD.bits()
|
||||
| ReprFlags::IS_LINEAR.bits();
|
||||
|
|
@ -183,6 +184,11 @@ impl ReprOptions {
|
|||
|
||||
/// Returns the discriminant type, given these `repr` options.
|
||||
/// This must only be called on enums!
|
||||
///
|
||||
/// This is the "typeck type" of the discriminant, which is effectively the maximum size:
|
||||
/// discriminant values will be wrapped to fit (with a lint). Layout can later decide to use a
|
||||
/// smaller type for the tag that stores the discriminant at runtime and that will work just
|
||||
/// fine, it just induces casts when getting/setting the discriminant.
|
||||
pub fn discr_type(&self) -> IntegerType {
|
||||
self.int.unwrap_or(IntegerType::Pointer(true))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,18 +12,13 @@
|
|||
#![allow(internal_features)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(no_crate_inject, attr(deny(warnings)))
|
||||
)]
|
||||
#![doc(rust_logo)]
|
||||
#![doc(test(no_crate_inject, attr(deny(warnings), allow(internal_features))))]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(unwrap_infallible)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ edition = "2024"
|
|||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
memchr = "2.7.4"
|
||||
memchr = "2.7.6"
|
||||
rustc-literal-escaper = "0.0.5"
|
||||
rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
|
|||
|
|
@ -714,6 +714,15 @@ impl Pat {
|
|||
}
|
||||
}
|
||||
|
||||
/// Strip off all reference patterns (`&`, `&mut`) and return the inner pattern.
|
||||
pub fn peel_refs(&self) -> &Pat {
|
||||
let mut current = self;
|
||||
while let PatKind::Ref(inner, _) = ¤t.kind {
|
||||
current = inner;
|
||||
}
|
||||
current
|
||||
}
|
||||
|
||||
/// Is this a `..` pattern?
|
||||
pub fn is_rest(&self) -> bool {
|
||||
matches!(self.kind, PatKind::Rest)
|
||||
|
|
@ -3759,10 +3768,29 @@ pub struct ConstItem {
|
|||
pub ident: Ident,
|
||||
pub generics: Generics,
|
||||
pub ty: Box<Ty>,
|
||||
pub expr: Option<Box<Expr>>,
|
||||
pub rhs: Option<ConstItemRhs>,
|
||||
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub enum ConstItemRhs {
|
||||
TypeConst(AnonConst),
|
||||
Body(Box<Expr>),
|
||||
}
|
||||
|
||||
impl ConstItemRhs {
|
||||
pub fn span(&self) -> Span {
|
||||
self.expr().span
|
||||
}
|
||||
|
||||
pub fn expr(&self) -> &Expr {
|
||||
match self {
|
||||
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
|
||||
ConstItemRhs::Body(expr) => expr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adding a new variant? Please update `test_item` in `tests/ui/macros/stringify.rs`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum ItemKind {
|
||||
|
|
|
|||
|
|
@ -5,19 +5,13 @@
|
|||
//! This API is completely unstable and subject to change.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(deny(warnings)))
|
||||
)]
|
||||
#![doc(rust_logo)]
|
||||
#![doc(test(attr(deny(warnings), allow(internal_features))))]
|
||||
#![feature(array_windows)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_order_by)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -423,6 +423,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
Closure,
|
||||
Const,
|
||||
ConstItem,
|
||||
ConstItemRhs,
|
||||
Defaultness,
|
||||
Delegation,
|
||||
DelegationMac,
|
||||
|
|
|
|||
|
|
@ -170,37 +170,36 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
ItemKind::Static(box ast::StaticItem {
|
||||
ident,
|
||||
ty: t,
|
||||
ty,
|
||||
safety: _,
|
||||
mutability: m,
|
||||
expr: e,
|
||||
define_opaque,
|
||||
}) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
let (ty, body_id) =
|
||||
self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy);
|
||||
let ty =
|
||||
self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
|
||||
let body_id = self.lower_const_body(span, e.as_deref());
|
||||
self.lower_define_opaque(hir_id, define_opaque);
|
||||
hir::ItemKind::Static(*m, ident, ty, body_id)
|
||||
}
|
||||
ItemKind::Const(box ast::ConstItem {
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
expr,
|
||||
define_opaque,
|
||||
..
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
}) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
let (generics, (ty, body_id)) = self.lower_generics(
|
||||
let (generics, (ty, rhs)) = self.lower_generics(
|
||||
generics,
|
||||
id,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||
|this| {
|
||||
this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy)
|
||||
let ty = this
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
||||
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span);
|
||||
(ty, rhs)
|
||||
},
|
||||
);
|
||||
self.lower_define_opaque(hir_id, &define_opaque);
|
||||
hir::ItemKind::Const(ident, generics, ty, body_id)
|
||||
hir::ItemKind::Const(ident, generics, ty, rhs)
|
||||
}
|
||||
ItemKind::Fn(box Fn {
|
||||
sig: FnSig { decl, header, span: fn_sig_span },
|
||||
|
|
@ -462,17 +461,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_const_item(
|
||||
&mut self,
|
||||
ty: &Ty,
|
||||
span: Span,
|
||||
body: Option<&Expr>,
|
||||
impl_trait_position: ImplTraitPosition,
|
||||
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
|
||||
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
|
||||
(ty, self.lower_const_body(span, body))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_use_tree(
|
||||
&mut self,
|
||||
|
|
@ -804,12 +792,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (ident, generics, kind, has_default) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem {
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
expr,
|
||||
define_opaque,
|
||||
..
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
}) => {
|
||||
let (generics, kind) = self.lower_generics(
|
||||
generics,
|
||||
|
|
@ -818,14 +801,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
let ty = this
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
||||
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
|
||||
|
||||
hir::TraitItemKind::Const(ty, body)
|
||||
let rhs = rhs
|
||||
.as_ref()
|
||||
.map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span));
|
||||
hir::TraitItemKind::Const(ty, rhs)
|
||||
},
|
||||
);
|
||||
|
||||
if define_opaque.is_some() {
|
||||
if expr.is_some() {
|
||||
if rhs.is_some() {
|
||||
self.lower_define_opaque(hir_id, &define_opaque);
|
||||
} else {
|
||||
self.dcx().span_err(
|
||||
|
|
@ -835,7 +819,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
(*ident, generics, kind, expr.is_some())
|
||||
(*ident, generics, kind, rhs.is_some())
|
||||
}
|
||||
AssocItemKind::Fn(box Fn {
|
||||
sig, ident, generics, body: None, define_opaque, ..
|
||||
|
|
@ -1022,12 +1006,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (ident, (generics, kind)) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem {
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
expr,
|
||||
define_opaque,
|
||||
..
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
}) => (
|
||||
*ident,
|
||||
self.lower_generics(
|
||||
|
|
@ -1037,9 +1016,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|this| {
|
||||
let ty = this
|
||||
.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
|
||||
let body = this.lower_const_body(i.span, expr.as_deref());
|
||||
this.lower_define_opaque(hir_id, &define_opaque);
|
||||
hir::ImplItemKind::Const(ty, body)
|
||||
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span);
|
||||
hir::ImplItemKind::Const(ty, rhs)
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -31,11 +31,8 @@
|
|||
//! in the HIR, especially for multiple identifiers.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use std::sync::Arc;
|
||||
|
|
@ -2330,6 +2327,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind: ct_kind })
|
||||
}
|
||||
|
||||
fn lower_const_item_rhs(
|
||||
&mut self,
|
||||
attrs: &[hir::Attribute],
|
||||
rhs: Option<&ConstItemRhs>,
|
||||
span: Span,
|
||||
) -> hir::ConstItemRhs<'hir> {
|
||||
match rhs {
|
||||
Some(ConstItemRhs::TypeConst(anon)) => {
|
||||
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg(anon))
|
||||
}
|
||||
None if attr::contains_name(attrs, sym::type_const) => {
|
||||
let const_arg = ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Error(
|
||||
DUMMY_SP,
|
||||
self.dcx().span_delayed_bug(DUMMY_SP, "no block"),
|
||||
),
|
||||
};
|
||||
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
|
||||
}
|
||||
Some(ConstItemRhs::Body(body)) => {
|
||||
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
|
||||
}
|
||||
None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)),
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_anon_const`].
|
||||
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ ast_passes_trait_fn_const =
|
|||
*[false] {""}
|
||||
}
|
||||
.make_impl_const_sugg = ... and declare the impl to be const instead
|
||||
.make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead
|
||||
.make_trait_const_sugg = ... and declare the trait to be const instead
|
||||
|
||||
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ enum SelfSemantic {
|
|||
}
|
||||
|
||||
enum TraitOrTraitImpl {
|
||||
Trait { span: Span, constness: Const },
|
||||
Trait { vis: Span, constness: Const },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span },
|
||||
}
|
||||
|
||||
|
|
@ -109,10 +109,10 @@ impl<'a> AstValidator<'a> {
|
|||
self.outer_trait_or_trait_impl = old;
|
||||
}
|
||||
|
||||
fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) {
|
||||
fn with_in_trait(&mut self, vis: Span, constness: Const, f: impl FnOnce(&mut Self)) {
|
||||
let old = mem::replace(
|
||||
&mut self.outer_trait_or_trait_impl,
|
||||
Some(TraitOrTraitImpl::Trait { span, constness }),
|
||||
Some(TraitOrTraitImpl::Trait { vis, constness }),
|
||||
);
|
||||
f(self);
|
||||
self.outer_trait_or_trait_impl = old;
|
||||
|
|
@ -265,10 +265,12 @@ impl<'a> AstValidator<'a> {
|
|||
None
|
||||
};
|
||||
|
||||
let map = self.sess.source_map();
|
||||
|
||||
let make_trait_const_sugg = if const_trait_impl
|
||||
&& let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent
|
||||
&& let &TraitOrTraitImpl::Trait { vis, constness: ast::Const::No } = parent
|
||||
{
|
||||
Some(span.shrink_to_lo())
|
||||
Some(map.span_extend_while_whitespace(vis).shrink_to_hi())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -279,7 +281,7 @@ impl<'a> AstValidator<'a> {
|
|||
in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
|
||||
const_context_label: parent_constness,
|
||||
remove_const_sugg: (
|
||||
self.sess.source_map().span_extend_while_whitespace(span),
|
||||
map.span_extend_while_whitespace(span),
|
||||
match parent_constness {
|
||||
Some(_) => rustc_errors::Applicability::MachineApplicable,
|
||||
None => rustc_errors::Applicability::MaybeIncorrect,
|
||||
|
|
@ -1165,13 +1167,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
..
|
||||
}) => {
|
||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||
// FIXME(const_trait_impl) remove this
|
||||
let alt_const_trait_span =
|
||||
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
|
||||
let constness = match (*constness, alt_const_trait_span) {
|
||||
(Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span),
|
||||
(Const::No, None) => Const::No,
|
||||
};
|
||||
if *is_auto == IsAuto::Yes {
|
||||
// Auto traits cannot have generics, super traits nor contain items.
|
||||
self.deny_generic_params(generics, ident.span);
|
||||
|
|
@ -1188,7 +1183,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||
});
|
||||
self.with_in_trait(item.span, constness, |this| {
|
||||
self.with_in_trait(item.vis.span, *constness, |this| {
|
||||
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
|
||||
});
|
||||
}
|
||||
|
|
@ -1239,9 +1234,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
});
|
||||
}
|
||||
ItemKind::Const(box ConstItem { defaultness, expr, .. }) => {
|
||||
ItemKind::Const(box ConstItem { defaultness, rhs, .. }) => {
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
if expr.is_none() {
|
||||
if rhs.is_none() {
|
||||
self.dcx().emit_err(errors::ConstWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
|
|
@ -1581,7 +1576,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|
||||
if let AssocCtxt::Impl { .. } = ctxt {
|
||||
match &item.kind {
|
||||
AssocItemKind::Const(box ConstItem { expr: None, .. }) => {
|
||||
AssocItemKind::Const(box ConstItem { rhs: None, .. }) => {
|
||||
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ pub(crate) struct TraitFnConst {
|
|||
pub make_impl_const_sugg: Option<Span>,
|
||||
#[suggestion(
|
||||
ast_passes_make_trait_const_sugg,
|
||||
code = "#[const_trait]\n",
|
||||
code = "const ",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
pub make_trait_const_sugg: Option<Span>,
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@
|
|||
//! by `rustc_ast_lowering`.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
pub mod ast_validation;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
mod helpers;
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
expr,
|
||||
rhs,
|
||||
define_opaque,
|
||||
}) => {
|
||||
self.print_item_const(
|
||||
|
|
@ -218,7 +218,7 @@ impl<'a> State<'a> {
|
|||
None,
|
||||
generics,
|
||||
ty,
|
||||
expr.as_deref(),
|
||||
rhs.as_ref().map(|ct| ct.expr()),
|
||||
&item.vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
|
|
@ -566,7 +566,7 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
expr,
|
||||
rhs,
|
||||
define_opaque,
|
||||
}) => {
|
||||
self.print_item_const(
|
||||
|
|
@ -574,7 +574,7 @@ impl<'a> State<'a> {
|
|||
None,
|
||||
generics,
|
||||
ty,
|
||||
expr.as_deref(),
|
||||
rhs.as_ref().map(|ct| ct.expr()),
|
||||
vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
|
|
|
|||
|
|
@ -12,13 +12,14 @@ use rustc_session::config::ExpectedValues;
|
|||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::parse::{ParseSess, feature_err};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::context::{AcceptContext, ShouldEmit, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
|
||||
use crate::session_diagnostics::{
|
||||
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
|
||||
ParsedDescription,
|
||||
};
|
||||
use crate::{
|
||||
AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics,
|
||||
|
|
@ -47,20 +48,19 @@ pub fn parse_cfg<'c, S: Stage>(
|
|||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
parse_cfg_entry(cx, single)
|
||||
parse_cfg_entry(cx, single).ok()
|
||||
}
|
||||
|
||||
pub(crate) fn parse_cfg_entry<S: Stage>(
|
||||
pub fn parse_cfg_entry<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
item: &MetaItemOrLitParser<'_>,
|
||||
) -> Option<CfgEntry> {
|
||||
Some(match item {
|
||||
) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
Ok(match item {
|
||||
MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() {
|
||||
ArgParser::List(list) => match meta.path().word_sym() {
|
||||
Some(sym::not) => {
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
return Err(cx.expected_single_argument(list.span));
|
||||
};
|
||||
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
|
||||
}
|
||||
|
|
@ -75,29 +75,24 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
|
|||
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
|
||||
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
|
||||
_ => {
|
||||
cx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
return Err(cx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: meta.span(),
|
||||
predicate: meta.path().to_string(),
|
||||
});
|
||||
return None;
|
||||
}));
|
||||
}
|
||||
},
|
||||
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
|
||||
let Some(name) = meta.path().word_sym() else {
|
||||
cx.expected_identifier(meta.path().span());
|
||||
return None;
|
||||
return Err(cx.expected_identifier(meta.path().span()));
|
||||
};
|
||||
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
|
||||
}
|
||||
},
|
||||
MetaItemOrLitParser::Lit(lit) => match lit.kind {
|
||||
LitKind::Bool(b) => CfgEntry::Bool(b, lit.span),
|
||||
_ => {
|
||||
cx.expected_identifier(lit.span);
|
||||
return None;
|
||||
}
|
||||
_ => return Err(cx.expected_identifier(lit.span)),
|
||||
},
|
||||
MetaItemOrLitParser::Err(_, _) => return None,
|
||||
MetaItemOrLitParser::Err(_, err) => return Err(*err),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -105,19 +100,22 @@ fn parse_cfg_entry_version<S: Stage>(
|
|||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
|
||||
let Some(version) = list.single() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
|
||||
return None;
|
||||
return Err(
|
||||
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span })
|
||||
);
|
||||
};
|
||||
let Some(version_lit) = version.lit() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() });
|
||||
return None;
|
||||
return Err(
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() })
|
||||
);
|
||||
};
|
||||
let Some(version_str) = version_lit.value_str() else {
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span });
|
||||
return None;
|
||||
return Err(
|
||||
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span })
|
||||
);
|
||||
};
|
||||
|
||||
let min_version = parse_version(version_str).or_else(|| {
|
||||
|
|
@ -127,14 +125,14 @@ fn parse_cfg_entry_version<S: Stage>(
|
|||
None
|
||||
});
|
||||
|
||||
Some(CfgEntry::Version(min_version, list.span))
|
||||
Ok(CfgEntry::Version(min_version, list.span))
|
||||
}
|
||||
|
||||
fn parse_cfg_entry_target<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
list: &MetaItemListParser<'_>,
|
||||
meta_span: Span,
|
||||
) -> Option<CfgEntry> {
|
||||
) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
if let Some(features) = cx.features_option()
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
|
|
@ -161,17 +159,16 @@ fn parse_cfg_entry_target<S: Stage>(
|
|||
|
||||
// Then, parse it as a name-value item
|
||||
let Some(name) = sub_item.path().word_sym() else {
|
||||
cx.expected_identifier(sub_item.path().span());
|
||||
return None;
|
||||
return Err(cx.expected_identifier(sub_item.path().span()));
|
||||
};
|
||||
let name = Symbol::intern(&format!("target_{name}"));
|
||||
if let Some(cfg) =
|
||||
if let Ok(cfg) =
|
||||
parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx)
|
||||
{
|
||||
result.push(cfg);
|
||||
}
|
||||
}
|
||||
Some(CfgEntry::All(result, list.span))
|
||||
Ok(CfgEntry::All(result, list.span))
|
||||
}
|
||||
|
||||
fn parse_name_value<S: Stage>(
|
||||
|
|
@ -180,35 +177,35 @@ fn parse_name_value<S: Stage>(
|
|||
value: Option<&NameValueParser>,
|
||||
span: Span,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> Option<CfgEntry> {
|
||||
) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
try_gate_cfg(name, span, cx.sess(), cx.features_option());
|
||||
|
||||
let value = match value {
|
||||
None => None,
|
||||
Some(value) => {
|
||||
let Some(value_str) = value.value_as_str() else {
|
||||
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
|
||||
return None;
|
||||
return Err(
|
||||
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()))
|
||||
);
|
||||
};
|
||||
Some((value_str, value.value_span))
|
||||
}
|
||||
};
|
||||
|
||||
Some(CfgEntry::NameValue { name, name_span, value, span })
|
||||
Ok(CfgEntry::NameValue { name, name_span, value, span })
|
||||
}
|
||||
|
||||
pub fn eval_config_entry(
|
||||
sess: &Session,
|
||||
cfg_entry: &CfgEntry,
|
||||
id: NodeId,
|
||||
features: Option<&Features>,
|
||||
emit_lints: ShouldEmit,
|
||||
) -> EvalConfigResult {
|
||||
match cfg_entry {
|
||||
CfgEntry::All(subs, ..) => {
|
||||
let mut all = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
let res = eval_config_entry(sess, sub, id, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if !res.as_bool() {
|
||||
all.get_or_insert(res);
|
||||
|
|
@ -219,7 +216,7 @@ pub fn eval_config_entry(
|
|||
CfgEntry::Any(subs, span) => {
|
||||
let mut any = None;
|
||||
for sub in subs {
|
||||
let res = eval_config_entry(sess, sub, id, features, emit_lints);
|
||||
let res = eval_config_entry(sess, sub, id, emit_lints);
|
||||
// We cannot short-circuit because `eval_config_entry` emits some lints
|
||||
if res.as_bool() {
|
||||
any.get_or_insert(res);
|
||||
|
|
@ -231,7 +228,7 @@ pub fn eval_config_entry(
|
|||
})
|
||||
}
|
||||
CfgEntry::Not(sub, span) => {
|
||||
if eval_config_entry(sess, sub, id, features, emit_lints).as_bool() {
|
||||
if eval_config_entry(sess, sub, id, emit_lints).as_bool() {
|
||||
EvalConfigResult::False { reason: cfg_entry.clone(), reason_span: *span }
|
||||
} else {
|
||||
EvalConfigResult::True
|
||||
|
|
@ -355,7 +352,8 @@ pub fn parse_cfg_attr(
|
|||
span,
|
||||
attr_span: cfg_attr.span,
|
||||
template: CFG_ATTR_TEMPLATE,
|
||||
attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
|
||||
path: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
|
||||
description: ParsedDescription::Attribute,
|
||||
reason,
|
||||
suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr),
|
||||
});
|
||||
|
|
@ -398,6 +396,7 @@ fn parse_cfg_attr_internal<'a>(
|
|||
.into_boxed_slice(),
|
||||
span: attribute.span,
|
||||
},
|
||||
ParsedDescription::Attribute,
|
||||
pred_span,
|
||||
CRATE_NODE_ID,
|
||||
features,
|
||||
|
|
@ -406,7 +405,8 @@ fn parse_cfg_attr_internal<'a>(
|
|||
parse_cfg_entry,
|
||||
&CFG_ATTR_TEMPLATE,
|
||||
)
|
||||
.ok_or_else(|| {
|
||||
.map_err(|_err: ErrorGuaranteed| {
|
||||
// We have an `ErrorGuaranteed` so this delayed bug cannot fail, but we need a `Diag` for the `PResult` so we make one anyways
|
||||
let mut diag = sess.dcx().struct_err(
|
||||
"cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.",
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
|
||||
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy};
|
||||
use rustc_session::parse::feature_err;
|
||||
|
||||
use super::prelude::*;
|
||||
|
|
@ -592,7 +592,8 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
r#"memory = "on|off""#,
|
||||
r#"memtag = "on|off""#,
|
||||
r#"shadow_call_stack = "on|off""#,
|
||||
r#"thread = "on|off""#
|
||||
r#"thread = "on|off""#,
|
||||
r#"realtime = "nonblocking|blocking|caller""#,
|
||||
]);
|
||||
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
|
|
@ -606,6 +607,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
|
||||
let mut on_set = SanitizerSet::empty();
|
||||
let mut off_set = SanitizerSet::empty();
|
||||
let mut rtsan = None;
|
||||
|
||||
for item in list.mixed() {
|
||||
let Some(item) = item.meta_item() else {
|
||||
|
|
@ -654,6 +656,17 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
|
||||
Some(sym::thread) => apply(SanitizerSet::THREAD),
|
||||
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
|
||||
Some(sym::realtime) => match value.value_as_str() {
|
||||
Some(sym::nonblocking) => rtsan = Some(RtsanSetting::Nonblocking),
|
||||
Some(sym::blocking) => rtsan = Some(RtsanSetting::Blocking),
|
||||
Some(sym::caller) => rtsan = Some(RtsanSetting::Caller),
|
||||
_ => {
|
||||
cx.expected_specific_argument_strings(
|
||||
value.value_span,
|
||||
&[sym::nonblocking, sym::blocking, sym::caller],
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
cx.expected_specific_argument_strings(
|
||||
item.path().span(),
|
||||
|
|
@ -666,6 +679,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
sym::shadow_call_stack,
|
||||
sym::thread,
|
||||
sym::hwaddress,
|
||||
sym::realtime,
|
||||
],
|
||||
);
|
||||
continue;
|
||||
|
|
@ -673,6 +687,15 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
|||
}
|
||||
}
|
||||
|
||||
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
|
||||
Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_pass_indirectly_in_non_rustic_abis];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use rustc_hir::attrs::*;
|
|||
use rustc_session::Session;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::kw;
|
||||
use rustc_target::spec::BinaryFormat;
|
||||
use rustc_target::spec::{Arch, BinaryFormat};
|
||||
|
||||
use super::prelude::*;
|
||||
use super::util::parse_single_integer;
|
||||
|
|
@ -396,7 +396,7 @@ impl LinkParser {
|
|||
)
|
||||
.emit();
|
||||
}
|
||||
*cfg = parse_cfg_entry(cx, link_cfg);
|
||||
*cfg = parse_cfg_entry(cx, link_cfg).ok();
|
||||
true
|
||||
}
|
||||
|
||||
|
|
@ -438,7 +438,7 @@ impl LinkParser {
|
|||
cx.expected_name_value(item.span(), Some(sym::import_name_type));
|
||||
return true;
|
||||
};
|
||||
if cx.sess().target.arch != "x86" {
|
||||
if cx.sess().target.arch != Arch::X86 {
|
||||
cx.emit_err(ImportNameTypeX86 { span: item.span() });
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ pub(crate) struct TypeConstParser;
|
|||
impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
|
||||
const PATH: &[Symbol] = &[sym::type_const];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]);
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
|
||||
}
|
||||
|
||||
|
|
@ -101,17 +102,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
|
||||
}
|
||||
|
||||
// FIXME(const_trait_impl): remove this
|
||||
// Const traits
|
||||
|
||||
pub(crate) struct ConstTraitParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
|
||||
const PATH: &[Symbol] = &[sym::const_trait];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
|
||||
}
|
||||
|
||||
// Specialization
|
||||
|
||||
pub(crate) struct SpecializationTraitParser;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ use crate::attributes::allow_unstable::{
|
|||
use crate::attributes::body::CoroutineParser;
|
||||
use crate::attributes::codegen_attrs::{
|
||||
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
|
||||
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
|
||||
TargetFeatureParser, TrackCallerParser, UsedParser,
|
||||
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
|
||||
RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
|
||||
TrackCallerParser, UsedParser,
|
||||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::crate_level::{
|
||||
|
|
@ -63,7 +64,7 @@ use crate::attributes::stability::{
|
|||
};
|
||||
use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
|
||||
use crate::attributes::traits::{
|
||||
AllowIncoherentImplParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser,
|
||||
AllowIncoherentImplParser, CoinductiveParser, DenyExplicitImplParser,
|
||||
DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, ParenSugarParser,
|
||||
PointeeParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
|
||||
UnsafeSpecializationMarkerParser,
|
||||
|
|
@ -71,7 +72,9 @@ use crate::attributes::traits::{
|
|||
use crate::attributes::transparency::TransparencyParser;
|
||||
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
|
||||
use crate::parser::{ArgParser, PathParser};
|
||||
use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
|
||||
use crate::session_diagnostics::{
|
||||
AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem,
|
||||
};
|
||||
use crate::target_checking::AllowedTargets;
|
||||
|
||||
type GroupType<S> = LazyLock<GroupTypeInner<S>>;
|
||||
|
|
@ -215,7 +218,6 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ColdParser>>,
|
||||
Single<WithoutArgs<ConstContinueParser>>,
|
||||
Single<WithoutArgs<ConstStabilityIndirectParser>>,
|
||||
Single<WithoutArgs<ConstTraitParser>>,
|
||||
Single<WithoutArgs<CoroutineParser>>,
|
||||
Single<WithoutArgs<DenyExplicitImplParser>>,
|
||||
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
|
||||
|
|
@ -241,6 +243,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
|
|
@ -353,6 +356,10 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
|
|||
/// Whether it is an inner or outer attribute
|
||||
pub(crate) attr_style: AttrStyle,
|
||||
|
||||
/// A description of the thing we are parsing using this attribute parser
|
||||
/// We are not only using these parsers for attributes, but also for macros such as the `cfg!()` macro.
|
||||
pub(crate) parsed_description: ParsedDescription,
|
||||
|
||||
/// The expected structure of the attribute.
|
||||
///
|
||||
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
|
||||
|
|
@ -431,7 +438,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedStringLiteral {
|
||||
byte_string: actual_literal.and_then(|i| {
|
||||
i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
|
||||
|
|
@ -446,7 +454,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -457,7 +466,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedList,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -468,7 +478,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span: args_span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedNoArgs,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -480,7 +491,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedIdentifier,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -493,7 +505,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedNameValue(name),
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -505,7 +518,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::DuplicateKey(key),
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -518,7 +532,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::UnexpectedLiteral,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -529,7 +544,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedSingleArgument,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -540,7 +556,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
|
||||
suggestions: self.suggestions(),
|
||||
})
|
||||
|
|
@ -556,7 +573,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
|
|
@ -577,7 +595,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: false,
|
||||
|
|
@ -597,7 +616,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
|
|||
span,
|
||||
attr_span: self.attr_span,
|
||||
template: self.template.clone(),
|
||||
attribute: self.attr_path.clone(),
|
||||
path: self.attr_path.clone(),
|
||||
description: self.parsed_description,
|
||||
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
|
||||
possibilities,
|
||||
strings: true,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
|||
|
||||
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
|
||||
use crate::parser::{ArgParser, MetaItemParser, PathParser};
|
||||
use crate::session_diagnostics::ParsedDescription;
|
||||
use crate::{Early, Late, OmitDoc, ShouldEmit};
|
||||
|
||||
/// Context created once, for example as part of the ast lowering
|
||||
|
|
@ -145,6 +146,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
normal_attr.item.span(),
|
||||
attr.style,
|
||||
path.get_attribute_path(),
|
||||
ParsedDescription::Attribute,
|
||||
target_span,
|
||||
target_node_id,
|
||||
features,
|
||||
|
|
@ -163,14 +165,15 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
inner_span: Span,
|
||||
attr_style: AttrStyle,
|
||||
attr_path: AttrPath,
|
||||
parsed_description: ParsedDescription,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
args: &I,
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option<T>,
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T,
|
||||
template: &AttributeTemplate,
|
||||
) -> Option<T> {
|
||||
) -> T {
|
||||
let mut parser = Self {
|
||||
features,
|
||||
tools: Vec::new(),
|
||||
|
|
@ -190,6 +193,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
attr_span,
|
||||
inner_span,
|
||||
attr_style,
|
||||
parsed_description,
|
||||
template,
|
||||
attr_path,
|
||||
};
|
||||
|
|
@ -310,6 +314,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
attr_span: lower_span(attr.span),
|
||||
inner_span: lower_span(attr.get_normal_item().span()),
|
||||
attr_style: attr.style,
|
||||
parsed_description: ParsedDescription::Attribute,
|
||||
template: &accept.template,
|
||||
attr_path: path.get_attribute_path(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -77,10 +77,7 @@
|
|||
//! containing both `C` and `packed` annotations.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
@ -106,12 +103,13 @@ mod target_checking;
|
|||
pub mod validate_attr;
|
||||
|
||||
pub use attributes::cfg::{
|
||||
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr,
|
||||
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
|
||||
};
|
||||
pub use attributes::cfg_old::*;
|
||||
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
|
||||
pub use context::{Early, Late, OmitDoc, ShouldEmit};
|
||||
pub use interface::AttributeParser;
|
||||
pub use lints::emit_attribute_lint;
|
||||
pub use session_diagnostics::ParsedDescription;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -610,20 +610,35 @@ pub(crate) enum AttributeParseErrorReason<'a> {
|
|||
ExpectedIdentifier,
|
||||
}
|
||||
|
||||
/// A description of a thing that can be parsed using an attribute parser.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ParsedDescription {
|
||||
/// Used when parsing attributes.
|
||||
Attribute,
|
||||
/// Used when parsing some macros, such as the `cfg!()` macro.
|
||||
Macro,
|
||||
}
|
||||
|
||||
pub(crate) struct AttributeParseError<'a> {
|
||||
pub(crate) span: Span,
|
||||
pub(crate) attr_span: Span,
|
||||
pub(crate) template: AttributeTemplate,
|
||||
pub(crate) attribute: AttrPath,
|
||||
pub(crate) path: AttrPath,
|
||||
pub(crate) description: ParsedDescription,
|
||||
pub(crate) reason: AttributeParseErrorReason<'a>,
|
||||
pub(crate) suggestions: Vec<String>,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let name = self.attribute.to_string();
|
||||
let name = self.path.to_string();
|
||||
|
||||
let mut diag = Diag::new(dcx, level, format!("malformed `{name}` attribute input"));
|
||||
let description = match self.description {
|
||||
ParsedDescription::Attribute => "attribute",
|
||||
ParsedDescription::Macro => "macro",
|
||||
};
|
||||
|
||||
let mut diag = Diag::new(dcx, level, format!("malformed `{name}` {description} input"));
|
||||
diag.span(self.attr_span);
|
||||
diag.code(E0539);
|
||||
match self.reason {
|
||||
|
|
@ -724,12 +739,12 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
diag.span_label(
|
||||
self.span,
|
||||
format!(
|
||||
"this attribute is only valid with {quote}{x}{quote} as an argument"
|
||||
"this {description} is only valid with {quote}{x}{quote} as an argument"
|
||||
),
|
||||
);
|
||||
}
|
||||
[first, second] => {
|
||||
diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
|
||||
diag.span_label(self.span, format!("this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
|
||||
}
|
||||
[first @ .., second_to_last, last] => {
|
||||
let mut res = String::new();
|
||||
|
|
@ -740,7 +755,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
"{quote}{second_to_last}{quote} or {quote}{last}{quote}"
|
||||
));
|
||||
|
||||
diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
|
||||
diag.span_label(self.span, format!("this {description} is only valid with one of the following arguments: {res}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -756,9 +771,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
|
|||
diag.span_suggestions(
|
||||
self.attr_span,
|
||||
if self.suggestions.len() == 1 {
|
||||
"must be of the form"
|
||||
"must be of the form".to_string()
|
||||
} else {
|
||||
"try changing it to one of the following valid forms of the attribute"
|
||||
format!("try changing it to one of the following valid forms of the {description}")
|
||||
},
|
||||
self.suggestions,
|
||||
Applicability::HasPlaceholders,
|
||||
|
|
|
|||
|
|
@ -21,10 +21,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(elided_lifetimes_in_paths)]
|
||||
#![allow(internal_features)]
|
||||
#![allow(unreachable_pub)] // because this crate is mostly generated code
|
||||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
// #![warn(unreachable_pub)] // don't use because this crate is mostly generated code
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -150,8 +150,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
|
||||
if the_place_err.local == ty::CAPTURE_STRUCT_LOCAL
|
||||
PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => {
|
||||
if local == ty::CAPTURE_STRUCT_LOCAL
|
||||
&& proj_base.is_empty()
|
||||
&& !self.upvars.is_empty()
|
||||
{
|
||||
|
|
@ -165,10 +165,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
", as `Fn` closures cannot mutate their captured variables".to_string()
|
||||
}
|
||||
} else {
|
||||
let source = self.borrowed_content_source(PlaceRef {
|
||||
local: the_place_err.local,
|
||||
projection: proj_base,
|
||||
});
|
||||
let source =
|
||||
self.borrowed_content_source(PlaceRef { local, projection: proj_base });
|
||||
let pointer_type = source.describe_for_immutable_place(self.infcx.tcx);
|
||||
opt_source = Some(source);
|
||||
if let Some(desc) = self.describe_place(access_place.as_ref()) {
|
||||
|
|
@ -335,10 +333,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: BindingMode(ByRef::No, Mutability::Not),
|
||||
opt_ty_info: Some(sp),
|
||||
pat_span,
|
||||
..
|
||||
})) => {
|
||||
if suggest {
|
||||
err.span_note(sp, "the binding is already a mutable borrow");
|
||||
err.span_suggestion_verbose(
|
||||
pat_span.shrink_to_lo(),
|
||||
"consider making the binding mutable if you need to reborrow \
|
||||
multiple times",
|
||||
"mut ".to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -356,9 +362,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
// give a best effort structured suggestion.
|
||||
err.span_suggestion_verbose(
|
||||
source_info.span.with_hi(source_info.span.lo() + BytePos(5)),
|
||||
"try removing `&mut` here",
|
||||
"if there is only one mutable reborrow, remove the `&mut`",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
// This can occur with things like `(&mut self).foo()`.
|
||||
|
|
@ -532,6 +538,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
PlaceRef { local, projection: [ProjectionElem::Deref] }
|
||||
if local == ty::CAPTURE_STRUCT_LOCAL && !self.upvars.is_empty() =>
|
||||
{
|
||||
self.point_at_binding_outside_closure(&mut err, local, access_place);
|
||||
self.expected_fn_found_fn_mut_call(&mut err, span, act);
|
||||
}
|
||||
|
||||
|
|
@ -950,6 +957,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// When modifying a binding from inside of an `Fn` closure, point at the binding definition.
|
||||
fn point_at_binding_outside_closure(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
local: Local,
|
||||
access_place: Place<'tcx>,
|
||||
) {
|
||||
let place = access_place.as_ref();
|
||||
for (index, elem) in place.projection.into_iter().enumerate() {
|
||||
if let ProjectionElem::Deref = elem {
|
||||
if index == 0 {
|
||||
if self.body.local_decls[local].is_ref_for_guard() {
|
||||
continue;
|
||||
}
|
||||
if let LocalInfo::StaticRef { .. } = *self.body.local_decls[local].local_info()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
|
||||
local,
|
||||
projection: place.projection.split_at(index + 1).0,
|
||||
}) {
|
||||
let var_index = field.index();
|
||||
let upvar = self.upvars[var_index];
|
||||
if let Some(hir_id) = upvar.info.capture_kind_expr_id {
|
||||
let node = self.infcx.tcx.hir_node(hir_id);
|
||||
if let hir::Node::Expr(expr) = node
|
||||
&& let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
|
||||
&& let hir::def::Res::Local(hir_id) = path.res
|
||||
&& let hir::Node::Pat(pat) = self.infcx.tcx.hir_node(hir_id)
|
||||
{
|
||||
let name = upvar.to_string(self.infcx.tcx);
|
||||
err.span_label(
|
||||
pat.span,
|
||||
format!("`{name}` declared here, outside the closure"),
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
|
||||
fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) {
|
||||
err.span_label(sp, format!("cannot {act}"));
|
||||
|
|
@ -962,6 +1013,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
let def_id = tcx.hir_enclosing_body_owner(fn_call_id);
|
||||
let mut look_at_return = true;
|
||||
|
||||
err.span_label(closure_span, "in this closure");
|
||||
// If the HIR node is a function or method call, get the DefId
|
||||
// of the callee function or method, the span, and args of the call expr
|
||||
let get_call_details = || {
|
||||
|
|
@ -1032,7 +1084,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
if let Some(span) = arg {
|
||||
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
|
||||
err.span_label(call_span, "expects `Fn` instead of `FnMut`");
|
||||
err.span_label(closure_span, "in this closure");
|
||||
look_at_return = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1059,7 +1110,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
sig.decl.output.span(),
|
||||
"change this to return `FnMut` instead of `Fn`",
|
||||
);
|
||||
err.span_label(closure_span, "in this closure");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(file_buffered)]
|
||||
|
|
@ -10,7 +9,6 @@
|
|||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(try_blocks)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
@ -119,7 +117,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
fn mir_borrowck(
|
||||
tcx: TyCtxt<'_>,
|
||||
def: LocalDefId,
|
||||
) -> Result<&DefinitionSiteHiddenTypes<'_>, ErrorGuaranteed> {
|
||||
) -> Result<&FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'_>>, ErrorGuaranteed> {
|
||||
assert!(!tcx.is_typeck_child(def.to_def_id()));
|
||||
let (input_body, _) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def));
|
||||
|
|
@ -130,7 +128,7 @@ fn mir_borrowck(
|
|||
Err(guar)
|
||||
} else if input_body.should_skip() {
|
||||
debug!("Skipping borrowck because of injected body");
|
||||
let opaque_types = DefinitionSiteHiddenTypes(Default::default());
|
||||
let opaque_types = Default::default();
|
||||
Ok(tcx.arena.alloc(opaque_types))
|
||||
} else {
|
||||
let mut root_cx = BorrowCheckRootCtxt::new(tcx, def, None);
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
|||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, OpaqueTypeStorageEntries};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::mir::{Body, ConstraintCategory, DefinitionSiteHiddenTypes};
|
||||
use rustc_middle::mir::{Body, ConstraintCategory};
|
||||
use rustc_middle::ty::{
|
||||
self, DefiningScopeKind, EarlyBinder, FallibleTypeFolder, GenericArg, GenericArgsRef,
|
||||
OpaqueHiddenType, OpaqueTypeKey, Region, RegionVid, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperFoldable, TypeVisitableExt, fold_regions,
|
||||
self, DefiningScopeKind, DefinitionSiteHiddenType, FallibleTypeFolder, GenericArg,
|
||||
GenericArgsRef, OpaqueTypeKey, ProvisionalHiddenType, Region, RegionVid, Ty, TyCtxt,
|
||||
TypeFoldable, TypeSuperFoldable, TypeVisitableExt, fold_regions,
|
||||
};
|
||||
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||
use rustc_span::Span;
|
||||
|
|
@ -48,7 +48,7 @@ pub(crate) enum DeferredOpaqueTypeError<'tcx> {
|
|||
/// The opaque type.
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
/// The hidden type containing the member region.
|
||||
hidden_type: OpaqueHiddenType<'tcx>,
|
||||
hidden_type: ProvisionalHiddenType<'tcx>,
|
||||
/// The unexpected region.
|
||||
member_region: Region<'tcx>,
|
||||
},
|
||||
|
|
@ -67,7 +67,7 @@ pub(crate) fn clone_and_resolve_opaque_types<'tcx>(
|
|||
infcx: &BorrowckInferCtxt<'tcx>,
|
||||
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
|
||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||
) -> (OpaqueTypeStorageEntries, Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>) {
|
||||
) -> (OpaqueTypeStorageEntries, Vec<(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)>) {
|
||||
let opaque_types = infcx.clone_opaque_types();
|
||||
let opaque_types_storage_num_entries = infcx.inner.borrow_mut().opaque_types().num_entries();
|
||||
let opaque_types = opaque_types
|
||||
|
|
@ -131,27 +131,26 @@ fn nll_var_to_universal_region<'tcx>(
|
|||
/// and errors if we end up with distinct hidden types.
|
||||
fn add_hidden_type<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
def_id: LocalDefId,
|
||||
hidden_ty: OpaqueHiddenType<'tcx>,
|
||||
hidden_ty: ty::DefinitionSiteHiddenType<'tcx>,
|
||||
) {
|
||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
|
||||
// `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
|
||||
// only know that once we convert the generic parameters to those of the opaque type.
|
||||
if let Some(prev) = hidden_types.0.get_mut(&def_id) {
|
||||
if prev.ty != hidden_ty.ty {
|
||||
let guar = hidden_ty.ty.error_reported().err().unwrap_or_else(|| {
|
||||
let (Ok(e) | Err(e)) = prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
|
||||
e
|
||||
});
|
||||
prev.ty = Ty::new_error(tcx, guar);
|
||||
if let Some(prev) = hidden_types.get_mut(&def_id) {
|
||||
if prev.ty == hidden_ty.ty {
|
||||
// Pick a better span if there is one.
|
||||
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
||||
prev.span = prev.span.substitute_dummy(hidden_ty.span);
|
||||
} else {
|
||||
let (Ok(guar) | Err(guar)) =
|
||||
prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit());
|
||||
*prev = ty::DefinitionSiteHiddenType::new_error(tcx, guar);
|
||||
}
|
||||
// Pick a better span if there is one.
|
||||
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
|
||||
prev.span = prev.span.substitute_dummy(hidden_ty.span);
|
||||
} else {
|
||||
hidden_types.0.insert(def_id, hidden_ty);
|
||||
hidden_types.insert(def_id, hidden_ty);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +161,7 @@ struct DefiningUse<'tcx> {
|
|||
/// to interact with code outside of `rustc_borrowck`.
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
arg_regions: Vec<RegionVid>,
|
||||
hidden_type: OpaqueHiddenType<'tcx>,
|
||||
hidden_type: ProvisionalHiddenType<'tcx>,
|
||||
}
|
||||
|
||||
/// This computes the actual hidden types of the opaque types and maps them to their
|
||||
|
|
@ -181,8 +180,8 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>(
|
|||
universal_region_relations: &Frozen<UniversalRegionRelations<'tcx>>,
|
||||
constraints: &MirTypeckRegionConstraints<'tcx>,
|
||||
location_map: Rc<DenseLocationMap>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
|
||||
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
|
||||
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
|
||||
let mut errors = Vec::new();
|
||||
// When computing the hidden type we need to track member constraints.
|
||||
|
|
@ -216,8 +215,8 @@ pub(crate) fn compute_definition_site_hidden_types<'tcx>(
|
|||
#[instrument(level = "debug", skip_all, ret)]
|
||||
fn collect_defining_uses<'tcx>(
|
||||
rcx: &mut RegionCtxt<'_, 'tcx>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
|
||||
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
|
||||
errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
|
||||
) -> Vec<DefiningUse<'tcx>> {
|
||||
let infcx = rcx.infcx;
|
||||
|
|
@ -240,7 +239,7 @@ fn collect_defining_uses<'tcx>(
|
|||
infcx.tcx,
|
||||
hidden_types,
|
||||
opaque_type_key.def_id,
|
||||
OpaqueHiddenType::new_error(infcx.tcx, guar),
|
||||
DefinitionSiteHiddenType::new_error(infcx.tcx, guar),
|
||||
),
|
||||
_ => debug!(?non_nll_opaque_type_key, ?err, "ignoring non-defining use"),
|
||||
}
|
||||
|
|
@ -276,7 +275,7 @@ fn collect_defining_uses<'tcx>(
|
|||
#[instrument(level = "debug", skip(rcx, hidden_types, defining_uses, errors))]
|
||||
fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
||||
rcx: &RegionCtxt<'_, 'tcx>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
defining_uses: &[DefiningUse<'tcx>],
|
||||
errors: &mut Vec<DeferredOpaqueTypeError<'tcx>>,
|
||||
) {
|
||||
|
|
@ -303,21 +302,20 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
|||
hidden_type.span,
|
||||
"opaque type with non-universal region args",
|
||||
);
|
||||
ty::OpaqueHiddenType::new_error(tcx, guar)
|
||||
ty::ProvisionalHiddenType::new_error(tcx, guar)
|
||||
}
|
||||
};
|
||||
|
||||
// Now that we mapped the member regions to their final value,
|
||||
// map the arguments of the opaque type key back to the parameters
|
||||
// of the opaque type definition.
|
||||
let ty = infcx
|
||||
let hidden_type = infcx
|
||||
.infer_opaque_definition_from_instantiation(opaque_type_key, hidden_type)
|
||||
.unwrap_or_else(|_| {
|
||||
Ty::new_error_with_message(
|
||||
rcx.infcx.tcx,
|
||||
hidden_type.span,
|
||||
"deferred invalid opaque type args",
|
||||
)
|
||||
let guar = tcx
|
||||
.dcx()
|
||||
.span_delayed_bug(hidden_type.span, "deferred invalid opaque type args");
|
||||
DefinitionSiteHiddenType::new_error(tcx, guar)
|
||||
});
|
||||
|
||||
// Sometimes, when the hidden type is an inference variable, it can happen that
|
||||
|
|
@ -325,7 +323,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
|||
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
|
||||
// writeback.
|
||||
if !rcx.infcx.tcx.use_typing_mode_borrowck() {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.skip_binder().kind()
|
||||
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
|
||||
&& alias_ty.args == opaque_type_key.args
|
||||
{
|
||||
|
|
@ -357,12 +355,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>(
|
|||
},
|
||||
));
|
||||
}
|
||||
add_hidden_type(
|
||||
tcx,
|
||||
hidden_types,
|
||||
opaque_type_key.def_id,
|
||||
OpaqueHiddenType { span: hidden_type.span, ty },
|
||||
);
|
||||
add_hidden_type(tcx, hidden_types, opaque_type_key.def_id, hidden_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -495,14 +488,13 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
|
|||
region_bound_pairs: &RegionBoundPairs<'tcx>,
|
||||
known_type_outlives_obligations: &[ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||
hidden_types: &mut DefinitionSiteHiddenTypes<'tcx>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
|
||||
hidden_types: &mut FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
opaque_types: &[(OpaqueTypeKey<'tcx>, ProvisionalHiddenType<'tcx>)],
|
||||
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
|
||||
let tcx = infcx.tcx;
|
||||
let mut errors = Vec::new();
|
||||
for &(key, hidden_type) in opaque_types {
|
||||
let Some(expected) = hidden_types.0.get(&key.def_id).map(|ty| EarlyBinder::bind(*ty))
|
||||
else {
|
||||
let Some(expected) = hidden_types.get(&key.def_id) else {
|
||||
if !tcx.use_typing_mode_borrowck() {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
|
||||
&& alias_ty.def_id == key.def_id.to_def_id()
|
||||
|
|
@ -521,20 +513,26 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
|
|||
hidden_type.span,
|
||||
"non-defining use in the defining scope with no defining uses",
|
||||
);
|
||||
add_hidden_type(tcx, hidden_types, key.def_id, OpaqueHiddenType::new_error(tcx, guar));
|
||||
add_hidden_type(
|
||||
tcx,
|
||||
hidden_types,
|
||||
key.def_id,
|
||||
DefinitionSiteHiddenType::new_error(tcx, guar),
|
||||
);
|
||||
continue;
|
||||
};
|
||||
|
||||
// We erase all non-member region of the opaque and need to treat these as existentials.
|
||||
let expected = ty::fold_regions(tcx, expected.instantiate(tcx, key.args), |re, _dbi| {
|
||||
match re.kind() {
|
||||
ty::ReErased => infcx.next_nll_region_var(
|
||||
NllRegionVariableOrigin::Existential { name: None },
|
||||
|| crate::RegionCtxt::Existential(None),
|
||||
),
|
||||
_ => re,
|
||||
}
|
||||
});
|
||||
let expected_ty =
|
||||
ty::fold_regions(tcx, expected.ty.instantiate(tcx, key.args), |re, _dbi| {
|
||||
match re.kind() {
|
||||
ty::ReErased => infcx.next_nll_region_var(
|
||||
NllRegionVariableOrigin::Existential { name: None },
|
||||
|| crate::RegionCtxt::Existential(None),
|
||||
),
|
||||
_ => re,
|
||||
}
|
||||
});
|
||||
|
||||
// We now simply equate the expected with the actual hidden type.
|
||||
let locations = Locations::All(hidden_type.span);
|
||||
|
|
@ -555,13 +553,18 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>(
|
|||
);
|
||||
// We need to normalize both types in the old solver before equatingt them.
|
||||
let actual_ty = ocx.normalize(&cause, infcx.param_env, hidden_type.ty);
|
||||
let expected_ty = ocx.normalize(&cause, infcx.param_env, expected.ty);
|
||||
let expected_ty = ocx.normalize(&cause, infcx.param_env, expected_ty);
|
||||
ocx.eq(&cause, infcx.param_env, actual_ty, expected_ty).map_err(|_| NoSolution)
|
||||
},
|
||||
"equating opaque types",
|
||||
),
|
||||
) {
|
||||
add_hidden_type(tcx, hidden_types, key.def_id, OpaqueHiddenType::new_error(tcx, guar));
|
||||
add_hidden_type(
|
||||
tcx,
|
||||
hidden_types,
|
||||
key.def_id,
|
||||
DefinitionSiteHiddenType::new_error(tcx, guar),
|
||||
);
|
||||
}
|
||||
}
|
||||
errors
|
||||
|
|
@ -676,8 +679,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
fn infer_opaque_definition_from_instantiation(
|
||||
&self,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
instantiated_ty: OpaqueHiddenType<'tcx>,
|
||||
) -> Result<Ty<'tcx>, NonDefiningUseReason<'tcx>> {
|
||||
instantiated_ty: ProvisionalHiddenType<'tcx>,
|
||||
) -> Result<ty::DefinitionSiteHiddenType<'tcx>, NonDefiningUseReason<'tcx>> {
|
||||
opaque_type_has_defining_use_args(
|
||||
self,
|
||||
opaque_type_key,
|
||||
|
|
@ -685,15 +688,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
DefiningScopeKind::MirBorrowck,
|
||||
)?;
|
||||
|
||||
let definition_ty = instantiated_ty
|
||||
.remap_generic_params_to_declaration_params(
|
||||
opaque_type_key,
|
||||
self.tcx,
|
||||
DefiningScopeKind::MirBorrowck,
|
||||
)
|
||||
.ty;
|
||||
|
||||
definition_ty.error_reported()?;
|
||||
let definition_ty = instantiated_ty.remap_generic_params_to_declaration_params(
|
||||
opaque_type_key,
|
||||
self.tcx,
|
||||
DefiningScopeKind::MirBorrowck,
|
||||
);
|
||||
definition_ty.ty.skip_binder().error_reported()?;
|
||||
Ok(definition_ty)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@ use crate::region_infer::opaque_types::{
|
|||
};
|
||||
use crate::type_check::{Locations, constraint_conversion};
|
||||
use crate::{
|
||||
ClosureRegionRequirements, CollectRegionConstraintsResult, DefinitionSiteHiddenTypes,
|
||||
PropagatedBorrowCheckResults, borrowck_check_region_constraints,
|
||||
borrowck_collect_region_constraints,
|
||||
ClosureRegionRequirements, CollectRegionConstraintsResult, PropagatedBorrowCheckResults,
|
||||
borrowck_check_region_constraints, borrowck_collect_region_constraints,
|
||||
};
|
||||
|
||||
/// The shared context used by both the root as well as all its nested
|
||||
|
|
@ -27,7 +26,7 @@ use crate::{
|
|||
pub(super) struct BorrowCheckRootCtxt<'tcx> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
root_def_id: LocalDefId,
|
||||
hidden_types: DefinitionSiteHiddenTypes<'tcx>,
|
||||
hidden_types: FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>,
|
||||
/// The region constraints computed by [borrowck_collect_region_constraints]. This uses
|
||||
/// an [FxIndexMap] to guarantee that iterating over it visits nested bodies before
|
||||
/// their parents.
|
||||
|
|
@ -72,7 +71,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
|
|||
&self.propagated_borrowck_results[&nested_body_def_id].used_mut_upvars
|
||||
}
|
||||
|
||||
pub(super) fn finalize(self) -> Result<&'tcx DefinitionSiteHiddenTypes<'tcx>, ErrorGuaranteed> {
|
||||
pub(super) fn finalize(
|
||||
self,
|
||||
) -> Result<&'tcx FxIndexMap<LocalDefId, ty::DefinitionSiteHiddenType<'tcx>>, ErrorGuaranteed>
|
||||
{
|
||||
if let Some(guar) = self.tainted_by_errors {
|
||||
Err(guar)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1046,8 +1046,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
&Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
|
||||
&Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
|
||||
&Rvalue::NullaryOp(NullOp::RuntimeChecks(_), _) => {}
|
||||
|
||||
Rvalue::ShallowInitBox(_operand, ty) => {
|
||||
let trait_ref =
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ builtin_macros_duplicate_macro_attribute = duplicated attribute
|
|||
|
||||
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
|
||||
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
|
||||
.cargo_typo = there is a similar Cargo environment variable: `{$suggested_var}`
|
||||
.custom = use `std::env::var({$var_expr})` to read the variable at run time
|
||||
|
||||
builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Unicode string
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub(crate) fn expand(
|
|||
|
||||
// Generate anonymous constant serving as container for the allocator methods.
|
||||
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
|
||||
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
||||
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@
|
|||
//! a literal `true` or `false` based on whether the given cfg matches the
|
||||
//! current compilation environment.
|
||||
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_ast::{AttrStyle, token};
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_attr_parsing::parser::MetaItemOrLitParser;
|
||||
use rustc_attr_parsing::{
|
||||
AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry,
|
||||
};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_parse::exp;
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_attr_parsing as attr};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
|
|
@ -21,38 +26,48 @@ pub(crate) fn expand_cfg(
|
|||
|
||||
ExpandResult::Ready(match parse_cfg(cx, sp, tts) {
|
||||
Ok(cfg) => {
|
||||
let matches_cfg = attr::cfg_matches(
|
||||
let matches_cfg = attr::eval_config_entry(
|
||||
cx.sess,
|
||||
&cfg,
|
||||
&cx.sess,
|
||||
cx.current_expansion.lint_node_id,
|
||||
Some(cx.ecfg.features),
|
||||
);
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
)
|
||||
.as_bool();
|
||||
|
||||
MacEager::expr(cx.expr_bool(sp, matches_cfg))
|
||||
}
|
||||
Err(err) => {
|
||||
let guar = err.emit();
|
||||
DummyResult::any(sp, guar)
|
||||
}
|
||||
Err(guar) => DummyResult::any(sp, guar),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_cfg<'a>(
|
||||
cx: &ExtCtxt<'a>,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
) -> PResult<'a, ast::MetaItemInner> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
|
||||
if p.token == token::Eof {
|
||||
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
|
||||
fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
let mut parser = cx.new_parser_from_tts(tts);
|
||||
if parser.token == token::Eof {
|
||||
return Err(cx.dcx().emit_err(errors::RequiresCfgPattern { span }));
|
||||
}
|
||||
|
||||
let cfg = p.parse_meta_item_inner()?;
|
||||
let meta = MetaItemOrLitParser::parse_single(&mut parser, ShouldEmit::ErrorsAndLints)
|
||||
.map_err(|diag| diag.emit())?;
|
||||
let cfg = AttributeParser::parse_single_args(
|
||||
cx.sess,
|
||||
span,
|
||||
span,
|
||||
AttrStyle::Inner,
|
||||
AttrPath { segments: vec![Ident::from_str("cfg")].into_boxed_slice(), span },
|
||||
ParsedDescription::Macro,
|
||||
span,
|
||||
cx.current_expansion.lint_node_id,
|
||||
Some(cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
&meta,
|
||||
parse_cfg_entry,
|
||||
&CFG_TEMPLATE,
|
||||
)?;
|
||||
|
||||
let _ = p.eat(exp!(Comma));
|
||||
let _ = parser.eat(exp!(Comma));
|
||||
|
||||
if !p.eat(exp!(Eof)) {
|
||||
return Err(cx.dcx().create_err(errors::OneCfgPattern { span }));
|
||||
if !parser.eat(exp!(Eof)) {
|
||||
return Err(cx.dcx().emit_err(errors::OneCfgPattern { span }));
|
||||
}
|
||||
|
||||
Ok(cfg)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use rustc_ast::token::{self, LitKind};
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{ExprKind, GenericArg, Mutability};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::edit_distance::edit_distance;
|
||||
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
|
|
@ -144,6 +145,12 @@ pub(crate) fn expand_env<'cx>(
|
|||
if let Some(msg_from_user) = custom_msg {
|
||||
cx.dcx()
|
||||
.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user })
|
||||
} else if let Some(suggested_var) = find_similar_cargo_var(var.as_str()) {
|
||||
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVarTypo {
|
||||
span,
|
||||
var: *symbol,
|
||||
suggested_var: Symbol::intern(suggested_var),
|
||||
})
|
||||
} else if is_cargo_env_var(var.as_str()) {
|
||||
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar {
|
||||
span,
|
||||
|
|
@ -176,3 +183,49 @@ fn is_cargo_env_var(var: &str) -> bool {
|
|||
|| var.starts_with("DEP_")
|
||||
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
|
||||
}
|
||||
|
||||
const KNOWN_CARGO_VARS: &[&str] = &[
|
||||
// List of known Cargo environment variables that are set for crates (not build scripts, OUT_DIR etc).
|
||||
// See: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
|
||||
"CARGO_PKG_VERSION",
|
||||
"CARGO_PKG_VERSION_MAJOR",
|
||||
"CARGO_PKG_VERSION_MINOR",
|
||||
"CARGO_PKG_VERSION_PATCH",
|
||||
"CARGO_PKG_VERSION_PRE",
|
||||
"CARGO_PKG_AUTHORS",
|
||||
"CARGO_PKG_NAME",
|
||||
"CARGO_PKG_DESCRIPTION",
|
||||
"CARGO_PKG_HOMEPAGE",
|
||||
"CARGO_PKG_REPOSITORY",
|
||||
"CARGO_PKG_LICENSE",
|
||||
"CARGO_PKG_LICENSE_FILE",
|
||||
"CARGO_PKG_RUST_VERSION",
|
||||
"CARGO_PKG_README",
|
||||
"CARGO_MANIFEST_DIR",
|
||||
"CARGO_MANIFEST_PATH",
|
||||
"CARGO_CRATE_NAME",
|
||||
"CARGO_BIN_NAME",
|
||||
"CARGO_PRIMARY_PACKAGE",
|
||||
];
|
||||
|
||||
fn find_similar_cargo_var(var: &str) -> Option<&'static str> {
|
||||
if !var.starts_with("CARGO_") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let lookup_len = var.chars().count();
|
||||
let max_dist = std::cmp::max(lookup_len, 3) / 3;
|
||||
let mut best_match = None;
|
||||
let mut best_distance = usize::MAX;
|
||||
|
||||
for &known_var in KNOWN_CARGO_VARS {
|
||||
if let Some(distance) = edit_distance(var, known_var, max_dist) {
|
||||
if distance < best_distance {
|
||||
best_distance = distance;
|
||||
best_match = Some(known_var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
best_match
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,6 +535,14 @@ pub(crate) enum EnvNotDefined<'a> {
|
|||
var_expr: &'a rustc_ast::Expr,
|
||||
},
|
||||
#[diag(builtin_macros_env_not_defined)]
|
||||
#[help(builtin_macros_cargo_typo)]
|
||||
CargoEnvVarTypo {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
var: Symbol,
|
||||
suggested_var: Symbol,
|
||||
},
|
||||
#[diag(builtin_macros_env_not_defined)]
|
||||
#[help(builtin_macros_custom)]
|
||||
CustomEnvVar {
|
||||
#[primary_span]
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub(crate) fn expand(
|
|||
|
||||
// Generate anonymous constant serving as container for the allocator methods.
|
||||
let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
|
||||
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
||||
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
|
|
@ -14,7 +12,6 @@
|
|||
#![feature(iter_order_by)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(proc_macro_quote)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -385,9 +385,9 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
|
|||
cx.attr_nested_word(sym::allow, sym::deprecated, span),
|
||||
]);
|
||||
|
||||
let block = cx.expr_block(
|
||||
let block = ast::ConstItemRhs::Body(cx.expr_block(
|
||||
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
|
||||
);
|
||||
));
|
||||
|
||||
let anon_constant = cx.item_const(
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -207,30 +207,30 @@ pub(crate) fn expand_test_or_bench(
|
|||
};
|
||||
|
||||
let test_fn = if is_bench {
|
||||
// A simple ident for a lambda
|
||||
let b = Ident::from_str_and_span("b", attr_sp);
|
||||
|
||||
// avoid name collisions by using the function name within the identifier, see bug #148275
|
||||
let bencher_param =
|
||||
Ident::from_str_and_span(&format!("__bench_{}", fn_.ident.name), attr_sp);
|
||||
cx.expr_call(
|
||||
sp,
|
||||
cx.expr_path(test_path("StaticBenchFn")),
|
||||
thin_vec![
|
||||
// #[coverage(off)]
|
||||
// |b| self::test::assert_test_result(
|
||||
// |__bench_fn_name| self::test::assert_test_result(
|
||||
coverage_off(cx.lambda1(
|
||||
sp,
|
||||
cx.expr_call(
|
||||
sp,
|
||||
cx.expr_path(test_path("assert_test_result")),
|
||||
thin_vec![
|
||||
// super::$test_fn(b)
|
||||
// super::$test_fn(__bench_fn_name)
|
||||
cx.expr_call(
|
||||
ret_ty_sp,
|
||||
cx.expr_path(cx.path(sp, vec![fn_.ident])),
|
||||
thin_vec![cx.expr_ident(sp, b)],
|
||||
thin_vec![cx.expr_ident(sp, bencher_param)],
|
||||
),
|
||||
],
|
||||
),
|
||||
b,
|
||||
bencher_param,
|
||||
)), // )
|
||||
],
|
||||
)
|
||||
|
|
@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
||||
define_opaque: None,
|
||||
// test::TestDescAndFn {
|
||||
expr: Some(
|
||||
rhs: Some(ast::ConstItemRhs::Body(
|
||||
cx.expr_struct(
|
||||
sp,
|
||||
test_path("TestDescAndFn"),
|
||||
|
|
@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
field("testfn", test_fn), // }
|
||||
],
|
||||
), // }
|
||||
),
|
||||
)),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
# FIXME re-enable once https://github.com/rust-lang/rust/issues/134863 is fixed.
|
||||
# task:
|
||||
# name: freebsd
|
||||
# freebsd_instance:
|
||||
# image: freebsd-13-2-release-amd64
|
||||
# setup_rust_script:
|
||||
# - pkg install -y git-tiny binutils
|
||||
# - curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
# - sh rustup.sh --default-toolchain none -y --profile=minimal
|
||||
# target_cache:
|
||||
# folder: build/cg_clif
|
||||
# prepare_script:
|
||||
# - . $HOME/.cargo/env
|
||||
# - ./y.sh prepare
|
||||
# test_script:
|
||||
# - . $HOME/.cargo/env
|
||||
# # Disabling incr comp reduces cache size and incr comp doesn't save as much
|
||||
# # on CI anyway.
|
||||
# - export CARGO_BUILD_INCREMENTAL=false
|
||||
# # Skip rand as it fails on FreeBSD due to rust-random/rand#1355
|
||||
# - ./y.sh test --skip-test test.rust-random/rand
|
||||
task:
|
||||
name: freebsd
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-2
|
||||
setup_rust_script:
|
||||
- pkg install -y git-tiny binutils
|
||||
- curl https://sh.rustup.rs -sSf --output rustup.sh
|
||||
- sh rustup.sh --default-toolchain none -y --profile=minimal
|
||||
target_cache:
|
||||
folder: build/cg_clif
|
||||
prepare_script:
|
||||
- . $HOME/.cargo/env
|
||||
- ./y.sh prepare
|
||||
test_script:
|
||||
- . $HOME/.cargo/env
|
||||
# Disabling incr comp reduces cache size and incr comp doesn't save as much
|
||||
# on CI anyway.
|
||||
- export CARGO_BUILD_INCREMENTAL=false
|
||||
# FIXME(rust-lang/rust#134863) necessary to avoid error when dlopening proc
|
||||
# macros during compilation of cg_clif.
|
||||
- export LD_STATIC_TLS_EXTRA=4096
|
||||
# Skip rand as it fails on FreeBSD due to rust-random/rand#1355
|
||||
- ./y.sh test --skip-test test.rust-random/rand
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
- os: ubuntu-24.04-arm
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-unknown-linux-gnu
|
||||
- os: macos-13
|
||||
- os: macos-15-intel
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
- os: ubuntu-24.04-arm
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-unknown-linux-gnu
|
||||
- os: macos-13
|
||||
- os: macos-15-intel
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
|
|
@ -187,7 +187,7 @@ jobs:
|
|||
- os: ubuntu-24.04-arm
|
||||
env:
|
||||
TARGET_TRIPLE: aarch64-unknown-linux-gnu
|
||||
- os: macos-13
|
||||
- os: macos-15-intel
|
||||
env:
|
||||
TARGET_TRIPLE: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
|
|
@ -231,7 +231,7 @@ jobs:
|
|||
release:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
if: ${{ github.ref == 'refs/heads/master' }}
|
||||
if: ${{ github.ref == 'refs/heads/main' }}
|
||||
needs: [rustfmt, test, bench, dist]
|
||||
|
||||
permissions:
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@
|
|||
"crates": [
|
||||
{
|
||||
"root_module": "./example/mini_core.rs",
|
||||
"edition": "2015",
|
||||
"edition": "2024",
|
||||
"deps": [],
|
||||
"cfg": [],
|
||||
},
|
||||
{
|
||||
"root_module": "./example/mini_core_hello_world.rs",
|
||||
"edition": "2015",
|
||||
"edition": "2024",
|
||||
"deps": [
|
||||
{
|
||||
"crate": 0,
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
},
|
||||
{
|
||||
"root_module": "./example/std_example.rs",
|
||||
"edition": "2015",
|
||||
"edition": "2024",
|
||||
"deps": [],
|
||||
"cfg": [],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
|
|
@ -28,57 +28,57 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f53499803b1607b6ee0ba0de4ba036e6da700c2e489fe8f9d0f683d0b84d31"
|
||||
checksum = "f502c60b6af2025c312b37788c089943ef03156a2910da1aa046bb39eb8f61c7"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-assembler-x64-meta"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aadaa5bc8430d0e7bb999459369bedd0e5816ad4a82a0e20748341c4e333eda"
|
||||
checksum = "2b7e21a74bcf08443a4ef800a4a257063e5c51ee4d7a3bd58da5262d10340830"
|
||||
dependencies = [
|
||||
"cranelift-srcgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2005fda2fc52a2dbce58229b4fb4483b70cbc806ba8ecc11b3f050c1a2d26cac"
|
||||
checksum = "f337d268865c292ad5df0669a9bbf6223ca41460292a20ad5b0a57b8e9f27f93"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bitset"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56935e02452ca1249d39ad5c45a96304d0b4300a158a391fd113451e0cd4483d"
|
||||
checksum = "c0e60319a8242c8d1c7b5a2444d140c416f903f75e0d84da3256fceb822bab85"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62612786bf00e10999f50217d6f455d02b31591155881a45a903d1a95d1a4043"
|
||||
checksum = "78dee669e447a1c68760bf7acee33835e99d564f0137b067f74d4718dfc9970d"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"cranelift-assembler-x64",
|
||||
|
|
@ -97,49 +97,50 @@ dependencies = [
|
|||
"serde",
|
||||
"smallvec",
|
||||
"target-lexicon",
|
||||
"wasmtime-math",
|
||||
"wasmtime-internal-math",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07bae789df91ef236079733af9df11d852256c64af196f0bc6471ea0f5f301be"
|
||||
checksum = "601f629d172b7230f41dd0e78ee797efaf7ec1a5e113c8f395f4027dff6a92ca"
|
||||
dependencies = [
|
||||
"cranelift-assembler-x64-meta",
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-srcgen",
|
||||
"heck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1be319616d36527782558a8312508757815f64deb19b094c7b8f4337229a9bc6"
|
||||
checksum = "15755c2660902c7d59d96f6551a66ef629650dc3fd405f9dad841e8c58c1a4a2"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-control"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8810ee1ab5e9bd5cff4c0c8d240e2009cb5c2b79888fde1d5256d605712314b7"
|
||||
checksum = "727bfca18705101a294ab9077ad214a8b762ea2bc9844389d0db233d7c61ec3b"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "086452c97cfbe116bf17dbe622dc5fdf2ea97299c7d4ce42460f284387c9928a"
|
||||
checksum = "15564c6f0c72750ca4374f40b044857cbc8087571e46d4c7ccdbdcc29b1dec8b"
|
||||
dependencies = [
|
||||
"cranelift-bitset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c27947010ab759330f252610c17a8cd64d123358be4f33164233d04fcd77b80"
|
||||
checksum = "16c681f2731f1cf68eed9f3b6811571823a5ac498f59c52b73736b68599defb3"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
|
|
@ -149,15 +150,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-isle"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec67bfb8bd55b1e9760eb9f5186dca8d81bd4d86110f8d5af01154a044c91802"
|
||||
checksum = "40cedc02f08307da019a3e06d3f20f772f829ff813aec975accb012f8930b688"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d67cdfc447f2abdb46bb30a6582cce189539c3c051c1d5330692376e1400edff"
|
||||
checksum = "c2864461448c72d15ae3311ea63df9c7e35f22f04683785f6715a0cf17e6577d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -169,15 +170,15 @@ dependencies = [
|
|||
"log",
|
||||
"region",
|
||||
"target-lexicon",
|
||||
"wasmtime-jit-icache-coherence",
|
||||
"windows-sys 0.59.0",
|
||||
"wasmtime-internal-jit-icache-coherence",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4597eaa52bca1ed111986c7a7f70cdbe192f83d271d627201365078e37b7e84"
|
||||
checksum = "2b31d249bbbccc4c1ae54701087d4d49d05951897691eef44f4a60e70252743b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -186,9 +187,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75a9b63edea46e013fce459c46e500462cb03a0490fdd9c18fe42b1dd7b93aa1"
|
||||
checksum = "db03ab51c60710eb83d0217725b77db4062aca83b35359f5e6aa99ed1c275977"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"libc",
|
||||
|
|
@ -197,9 +198,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce706f0166d5b7f31693dff521e87cb9858e12adf22ffcde93c4a2826f8f04a9"
|
||||
checksum = "7131e0eb45ee10b0bd6082d0c0114c2e9a670b034d46774b39d0fc5c0ed7cedf"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
|
@ -212,24 +213,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cranelift-srcgen"
|
||||
version = "0.121.0"
|
||||
version = "0.125.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5870e266df8237b56cc98b04f5739c228565c92dd629ec6c66efa87271a158"
|
||||
checksum = "3d7a06c330b7994a891ad5b622ebc9aefcd17beae832dd25f577cf60c13426bf"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
|
|
@ -239,15 +240,15 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
|
|||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
|
|
@ -256,18 +257,24 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
version = "0.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
||||
dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.0"
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
|
@ -275,18 +282,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
version = "0.2.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets",
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -297,30 +304,30 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "mach2"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||
checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown",
|
||||
|
|
@ -330,27 +337,27 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regalloc2"
|
||||
version = "0.12.2"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734"
|
||||
checksum = "efd8138ce7c3d7c13be4f61893154b5d711bd798d2d7be3ecb8dcc7e7a06ca98"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"bumpalo",
|
||||
|
|
@ -374,9 +381,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.0"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_codegen_cranelift"
|
||||
|
|
@ -398,18 +405,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -418,9 +425,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
|
|
@ -430,9 +437,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.95"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -441,53 +448,59 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.13.1"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc12939a1c9b9d391e0b7135f72fd30508b73450753e28341fed159317582a77"
|
||||
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-jit-icache-coherence"
|
||||
version = "34.0.0"
|
||||
name = "wasmtime-internal-jit-icache-coherence"
|
||||
version = "38.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eedc0324e37cf39b049f4dca0c30997eaab49f09006d5f4c1994e64e7b7dba8"
|
||||
checksum = "8d0a76f1a6e887cc1b551b02dfd6e2ce5f6738e8cacd9ad7284f6ac1aac4698f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-math"
|
||||
version = "34.0.0"
|
||||
name = "wasmtime-internal-math"
|
||||
version = "38.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd35fae4cf51d2b4a9bd2ef04b0eb309fa1849cab6a6ab5ac27cbd054ea284d"
|
||||
checksum = "b900df4252ad86547e7f2b2c00201b006db4e864893bedfb3aca32b23d81868a"
|
||||
dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -496,14 +509,31 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm 0.52.6",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
"windows_i686_gnullvm 0.53.0",
|
||||
"windows_i686_msvc 0.53.0",
|
||||
"windows_x86_64_gnu 0.53.0",
|
||||
"windows_x86_64_gnullvm 0.53.0",
|
||||
"windows_x86_64_msvc 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -512,44 +542,92 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
[package]
|
||||
name = "rustc_codegen_cranelift"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
# These have to be in sync with each other
|
||||
cranelift-codegen = { version = "0.121.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
|
||||
cranelift-frontend = { version = "0.121.0" }
|
||||
cranelift-module = { version = "0.121.0" }
|
||||
cranelift-native = { version = "0.121.0" }
|
||||
cranelift-jit = { version = "0.121.0", optional = true }
|
||||
cranelift-object = { version = "0.121.0" }
|
||||
cranelift-codegen = { version = "0.125.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch"] }
|
||||
cranelift-frontend = { version = "0.125.0" }
|
||||
cranelift-module = { version = "0.125.0" }
|
||||
cranelift-native = { version = "0.125.0" }
|
||||
cranelift-jit = { version = "0.125.0", optional = true }
|
||||
cranelift-object = { version = "0.125.0" }
|
||||
target-lexicon = "0.13"
|
||||
gimli = { version = "0.31", default-features = false, features = ["write"] }
|
||||
object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
gimli = { version = "0.32", default-features = false, features = ["write"] }
|
||||
object = { version = "0.37.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
|
||||
|
||||
indexmap = "2.0.0"
|
||||
libloading = { version = "0.8.0", optional = true }
|
||||
|
|
@ -24,12 +24,12 @@ smallvec = "1.8.1"
|
|||
|
||||
[patch.crates-io]
|
||||
# Uncomment to use an unreleased version of cranelift
|
||||
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-34.0.0", version = "0.121.0" }
|
||||
#cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
#cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
#cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
#cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
#cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
#cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git", branch = "release-38.0.0" }
|
||||
|
||||
# Uncomment to use local checkout of cranelift
|
||||
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
|
||||
|
|
@ -46,6 +46,7 @@ smallvec = "1.8.1"
|
|||
unstable-features = ["jit", "inline_asm_sym"]
|
||||
jit = ["cranelift-jit", "libloading"]
|
||||
inline_asm_sym = []
|
||||
unwinding = [] # Not yet included in unstable-features for performance reasons
|
||||
|
||||
[package.metadata.rust-analyzer]
|
||||
rustc_private = true
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ The Cranelift codegen backend is distributed in nightly builds on Linux, macOS a
|
|||
install it using Rustup, you can do that by running:
|
||||
|
||||
```bash
|
||||
$ rustup component add rustc-codegen-cranelift-preview --toolchain nightly
|
||||
rustup component add rustc-codegen-cranelift-preview --toolchain nightly
|
||||
```
|
||||
|
||||
Once it is installed, you can enable it with one of the following approaches:
|
||||
|
|
@ -47,16 +47,16 @@ If you want to use `cargo clif build` instead of having to specify the full path
|
|||
If you want to build the backend manually, you can download it from GitHub and build it yourself:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/rust-lang/rustc_codegen_cranelift
|
||||
$ cd rustc_codegen_cranelift
|
||||
$ ./y.sh build
|
||||
git clone https://github.com/rust-lang/rustc_codegen_cranelift
|
||||
cd rustc_codegen_cranelift
|
||||
./y.sh build
|
||||
```
|
||||
|
||||
To run the test suite replace the last command with:
|
||||
|
||||
```bash
|
||||
$ ./y.sh prepare # only needs to be run the first time
|
||||
$ ./test.sh
|
||||
./y.sh prepare # only needs to be run the first time
|
||||
./test.sh
|
||||
```
|
||||
|
||||
For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`.
|
||||
|
|
@ -66,7 +66,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
|||
|OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)|
|
||||
|---|---|---|---|---|
|
||||
|Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]|
|
||||
|FreeBSD|✅[^no-rustup]|❓|❓|❓|
|
||||
|FreeBSD|✅[^no-rustup][^tls]|❓|❓|❓|
|
||||
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|
||||
|Other unixes|❓|❓|❓|❓|
|
||||
|macOS|✅|✅|N/A|N/A|
|
||||
|
|
@ -80,6 +80,7 @@ Not all targets are available as rustup component for nightly. See notes in the
|
|||
|
||||
[^xcoff]: XCOFF object file format is not supported.
|
||||
[^no-rustup]: Not available as [rustup component for nightly](https://rust-lang.github.io/rustup-components-history/). You can build it yourself.
|
||||
[^tls]: FreeBSD requires setting `LD_STATIC_TLS_EXTRA=4096` to build cg_clif. In addition you need at least FreeBSD 14.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
@ -90,7 +91,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo
|
|||
In the directory with your project (where you can do the usual `cargo build`), run:
|
||||
|
||||
```bash
|
||||
$ $cg_clif_dir/dist/cargo-clif build
|
||||
$cg_clif_dir/dist/cargo-clif build
|
||||
```
|
||||
|
||||
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
|
||||
|
|
@ -104,7 +105,7 @@ See [rustc_testing.md](docs/rustc_testing.md).
|
|||
## Not yet supported
|
||||
|
||||
* SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported)
|
||||
* Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default)
|
||||
* Unwinding on panics ([experimental and not supported on Windows and macOS](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1567), `-Cpanic=abort` is enabled by default)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ pub(crate) fn run(
|
|||
cg_clif_dylib: &CodegenBackend,
|
||||
rustup_toolchain_name: Option<&str>,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
panic_unwind_support: bool,
|
||||
) {
|
||||
std::fs::create_dir_all(&dirs.download_dir).unwrap();
|
||||
ABI_CAFE_REPO.fetch(dirs);
|
||||
|
|
@ -32,6 +33,7 @@ pub(crate) fn run(
|
|||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
bootstrap_host_compiler.triple.clone(),
|
||||
panic_unwind_support,
|
||||
);
|
||||
|
||||
eprintln!("Running abi-cafe");
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ fn hyperfine_command(
|
|||
}
|
||||
|
||||
for &(name, cmd) in cmds {
|
||||
if name != "" {
|
||||
if !name.is_empty() {
|
||||
bench.arg("-n").arg(name);
|
||||
}
|
||||
bench.arg(cmd);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ pub(crate) fn build_backend(
|
|||
dirs: &Dirs,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
use_unstable_features: bool,
|
||||
panic_unwind_support: bool,
|
||||
) -> PathBuf {
|
||||
let _group = LogGroup::guard("Build backend");
|
||||
|
||||
let mut cmd = CG_CLIF.build(&bootstrap_host_compiler, dirs);
|
||||
let mut cmd = CG_CLIF.build(bootstrap_host_compiler, dirs);
|
||||
|
||||
let mut rustflags = rustflags_from_env("RUSTFLAGS");
|
||||
rustflags.push("-Zallow-features=rustc_private,f16,f128".to_owned());
|
||||
|
|
@ -31,6 +32,10 @@ pub(crate) fn build_backend(
|
|||
cmd.arg("--features").arg("unstable-features");
|
||||
}
|
||||
|
||||
if panic_unwind_support {
|
||||
cmd.arg("--features").arg("unwinding");
|
||||
}
|
||||
|
||||
cmd.arg("--release");
|
||||
|
||||
eprintln!("[BUILD] rustc_codegen_cranelift");
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ pub(crate) fn build_sysroot(
|
|||
bootstrap_host_compiler: &Compiler,
|
||||
rustup_toolchain_name: Option<&str>,
|
||||
target_triple: String,
|
||||
panic_unwind_support: bool,
|
||||
) -> Compiler {
|
||||
let _guard = LogGroup::guard("Build sysroot");
|
||||
|
||||
|
|
@ -48,10 +49,14 @@ pub(crate) fn build_sysroot(
|
|||
let mut build_cargo_wrapper_cmd = Command::new(&bootstrap_host_compiler.rustc);
|
||||
let wrapper_path = dist_dir.join(&wrapper_name);
|
||||
build_cargo_wrapper_cmd
|
||||
.arg(dirs.source_dir.join("scripts").join(&format!("{wrapper}.rs")))
|
||||
.arg(dirs.source_dir.join("scripts").join(format!("{wrapper}.rs")))
|
||||
.arg("-o")
|
||||
.arg(&wrapper_path)
|
||||
.arg("-Cstrip=debuginfo");
|
||||
.arg("-Cstrip=debuginfo")
|
||||
.arg("--check-cfg=cfg(support_panic_unwind)");
|
||||
if panic_unwind_support {
|
||||
build_cargo_wrapper_cmd.arg("--cfg").arg("support_panic_unwind");
|
||||
}
|
||||
if let Some(rustup_toolchain_name) = &rustup_toolchain_name {
|
||||
build_cargo_wrapper_cmd
|
||||
.env("TOOLCHAIN_NAME", rustup_toolchain_name)
|
||||
|
|
@ -77,6 +82,7 @@ pub(crate) fn build_sysroot(
|
|||
bootstrap_host_compiler.clone(),
|
||||
&cg_clif_dylib_path,
|
||||
sysroot_kind,
|
||||
panic_unwind_support,
|
||||
);
|
||||
host.install_into_sysroot(dist_dir);
|
||||
|
||||
|
|
@ -91,6 +97,7 @@ pub(crate) fn build_sysroot(
|
|||
},
|
||||
&cg_clif_dylib_path,
|
||||
sysroot_kind,
|
||||
panic_unwind_support,
|
||||
)
|
||||
.install_into_sysroot(dist_dir);
|
||||
}
|
||||
|
|
@ -134,19 +141,20 @@ impl SysrootTarget {
|
|||
static STDLIB_SRC: RelPath = RelPath::build("stdlib");
|
||||
static STANDARD_LIBRARY: CargoProject =
|
||||
CargoProject::new(&RelPath::build("stdlib/library/sysroot"), "stdlib_target");
|
||||
static RTSTARTUP_SYSROOT: RelPath = RelPath::build("rtstartup");
|
||||
|
||||
fn build_sysroot_for_triple(
|
||||
dirs: &Dirs,
|
||||
compiler: Compiler,
|
||||
cg_clif_dylib_path: &CodegenBackend,
|
||||
sysroot_kind: SysrootKind,
|
||||
panic_unwind_support: bool,
|
||||
) -> SysrootTarget {
|
||||
match sysroot_kind {
|
||||
SysrootKind::None => build_rtstartup(dirs, &compiler)
|
||||
.unwrap_or(SysrootTarget { triple: compiler.triple, libs: vec![] }),
|
||||
SysrootKind::None => SysrootTarget { triple: compiler.triple, libs: vec![] },
|
||||
SysrootKind::Llvm => build_llvm_sysroot_for_triple(compiler),
|
||||
SysrootKind::Clif => build_clif_sysroot_for_triple(dirs, compiler, cg_clif_dylib_path),
|
||||
SysrootKind::Clif => {
|
||||
build_clif_sysroot_for_triple(dirs, compiler, cg_clif_dylib_path, panic_unwind_support)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,25 +196,28 @@ fn build_clif_sysroot_for_triple(
|
|||
dirs: &Dirs,
|
||||
mut compiler: Compiler,
|
||||
cg_clif_dylib_path: &CodegenBackend,
|
||||
panic_unwind_support: bool,
|
||||
) -> SysrootTarget {
|
||||
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
|
||||
|
||||
if let Some(rtstartup_target_libs) = build_rtstartup(dirs, &compiler) {
|
||||
rtstartup_target_libs.install_into_sysroot(&RTSTARTUP_SYSROOT.to_path(dirs));
|
||||
|
||||
target_libs.libs.extend(rtstartup_target_libs.libs);
|
||||
}
|
||||
|
||||
let build_dir = STANDARD_LIBRARY.target_dir(dirs).join(&compiler.triple).join("release");
|
||||
|
||||
if !config::get_bool("keep_sysroot") {
|
||||
let sysroot_src_orig = get_default_sysroot(&compiler.rustc).join("lib/rustlib/src/rust");
|
||||
assert!(sysroot_src_orig.exists());
|
||||
|
||||
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
|
||||
|
||||
// Cleanup the deps dir, but keep build scripts and the incremental cache for faster
|
||||
// recompilation as they are not affected by changes in cg_clif.
|
||||
ensure_empty_dir(&build_dir.join("deps"));
|
||||
}
|
||||
|
||||
// Build sysroot
|
||||
let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned(), "-Cpanic=abort".to_owned()];
|
||||
let mut rustflags = vec!["-Zforce-unstable-if-unmarked".to_owned()];
|
||||
if !panic_unwind_support {
|
||||
rustflags.push("-Cpanic=abort".to_owned());
|
||||
}
|
||||
match cg_clif_dylib_path {
|
||||
CodegenBackend::Local(path) => {
|
||||
rustflags.push(format!("-Zcodegen-backend={}", path.to_str().unwrap()));
|
||||
|
|
@ -215,9 +226,7 @@ fn build_clif_sysroot_for_triple(
|
|||
rustflags.push(format!("-Zcodegen-backend={name}"));
|
||||
}
|
||||
};
|
||||
// Necessary for MinGW to find rsbegin.o and rsend.o
|
||||
rustflags.push("--sysroot".to_owned());
|
||||
rustflags.push(RTSTARTUP_SYSROOT.to_path(dirs).to_str().unwrap().to_owned());
|
||||
rustflags.push("--sysroot=/dev/null".to_owned());
|
||||
|
||||
// Incremental compilation by default disables mir inlining. This leads to both a decent
|
||||
// compile perf and a significant runtime perf regression. As such forcefully enable mir
|
||||
|
|
@ -258,38 +267,3 @@ fn build_clif_sysroot_for_triple(
|
|||
|
||||
target_libs
|
||||
}
|
||||
|
||||
fn build_rtstartup(dirs: &Dirs, compiler: &Compiler) -> Option<SysrootTarget> {
|
||||
if !config::get_bool("keep_sysroot") {
|
||||
let sysroot_src_orig = get_default_sysroot(&compiler.rustc).join("lib/rustlib/src/rust");
|
||||
assert!(sysroot_src_orig.exists());
|
||||
|
||||
apply_patches(dirs, "stdlib", &sysroot_src_orig, &STDLIB_SRC.to_path(dirs));
|
||||
}
|
||||
|
||||
if !compiler.triple.ends_with("windows-gnu") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let rtstartup_sysroot = RTSTARTUP_SYSROOT.to_path(dirs);
|
||||
ensure_empty_dir(&rtstartup_sysroot);
|
||||
|
||||
let rtstartup_src = STDLIB_SRC.to_path(dirs).join("library").join("rtstartup");
|
||||
let mut target_libs = SysrootTarget { triple: compiler.triple.clone(), libs: vec![] };
|
||||
|
||||
for file in ["rsbegin", "rsend"] {
|
||||
let obj = rtstartup_sysroot.join(format!("{file}.o"));
|
||||
let mut build_rtstartup_cmd = Command::new(&compiler.rustc);
|
||||
build_rtstartup_cmd
|
||||
.arg("--target")
|
||||
.arg(&compiler.triple)
|
||||
.arg("--emit=obj")
|
||||
.arg("-o")
|
||||
.arg(&obj)
|
||||
.arg(rtstartup_src.join(format!("{file}.rs")));
|
||||
spawn_and_wait(build_rtstartup_cmd);
|
||||
target_libs.libs.push(obj.clone());
|
||||
}
|
||||
|
||||
Some(target_libs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ fn main() {
|
|||
let mut download_dir = None;
|
||||
let mut sysroot_kind = SysrootKind::Clif;
|
||||
let mut use_unstable_features = true;
|
||||
let mut panic_unwind_support = false;
|
||||
let mut frozen = false;
|
||||
let mut skip_tests = vec![];
|
||||
let mut use_backend = None;
|
||||
|
|
@ -108,6 +109,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
"--no-unstable-features" => use_unstable_features = false,
|
||||
"--panic-unwind-support" => panic_unwind_support = true,
|
||||
"--frozen" => frozen = true,
|
||||
"--skip-test" => {
|
||||
// FIXME check that all passed in tests actually exist
|
||||
|
|
@ -201,6 +203,7 @@ fn main() {
|
|||
&dirs,
|
||||
&bootstrap_host_compiler,
|
||||
use_unstable_features,
|
||||
panic_unwind_support,
|
||||
))
|
||||
};
|
||||
match command {
|
||||
|
|
@ -212,6 +215,7 @@ fn main() {
|
|||
&dirs,
|
||||
sysroot_kind,
|
||||
use_unstable_features,
|
||||
panic_unwind_support,
|
||||
&skip_tests.iter().map(|test| &**test).collect::<Vec<_>>(),
|
||||
&cg_clif_dylib,
|
||||
&bootstrap_host_compiler,
|
||||
|
|
@ -230,6 +234,7 @@ fn main() {
|
|||
&cg_clif_dylib,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
&bootstrap_host_compiler,
|
||||
panic_unwind_support,
|
||||
);
|
||||
}
|
||||
Command::Build => {
|
||||
|
|
@ -240,6 +245,7 @@ fn main() {
|
|||
&bootstrap_host_compiler,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
target_triple,
|
||||
panic_unwind_support,
|
||||
);
|
||||
}
|
||||
Command::Bench => {
|
||||
|
|
@ -250,6 +256,7 @@ fn main() {
|
|||
&bootstrap_host_compiler,
|
||||
rustup_toolchain_name.as_deref(),
|
||||
target_triple,
|
||||
panic_unwind_support,
|
||||
);
|
||||
bench::benchmark(&dirs, &compiler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,25 +2,19 @@ use std::path::{Path, PathBuf};
|
|||
use std::process::{Command, Stdio};
|
||||
|
||||
pub(crate) fn get_host_triple(rustc: &Path) -> String {
|
||||
let version_info =
|
||||
Command::new(rustc).stderr(Stdio::inherit()).args(&["-vV"]).output().unwrap().stdout;
|
||||
String::from_utf8(version_info)
|
||||
let version_info = Command::new(rustc)
|
||||
.stderr(Stdio::inherit())
|
||||
.args(["--print", "host-tuple"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.lines()
|
||||
.to_owned()
|
||||
.find(|line| line.starts_with("host"))
|
||||
.unwrap()
|
||||
.split(":")
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.to_owned()
|
||||
.stdout;
|
||||
String::from_utf8(version_info).unwrap().trim().to_owned()
|
||||
}
|
||||
|
||||
pub(crate) fn get_toolchain_name() -> String {
|
||||
let active_toolchain = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["show", "active-toolchain"])
|
||||
.args(["show", "active-toolchain"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
|
|
@ -33,7 +27,7 @@ pub(crate) fn get_cargo_path() -> PathBuf {
|
|||
}
|
||||
let cargo_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "cargo"])
|
||||
.args(["which", "cargo"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
|
|
@ -46,7 +40,7 @@ pub(crate) fn get_rustc_path() -> PathBuf {
|
|||
}
|
||||
let rustc_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "rustc"])
|
||||
.args(["which", "rustc"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
|
|
@ -59,7 +53,7 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
|
|||
}
|
||||
let rustc_path = Command::new("rustup")
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["which", "rustdoc"])
|
||||
.args(["which", "rustdoc"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
|
|
@ -69,7 +63,7 @@ pub(crate) fn get_rustdoc_path() -> PathBuf {
|
|||
pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
|
||||
let default_sysroot = Command::new(rustc)
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&["--print", "sysroot"])
|
||||
.args(["--print", "sysroot"])
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
|
|
@ -80,7 +74,7 @@ pub(crate) fn get_default_sysroot(rustc: &Path) -> PathBuf {
|
|||
pub(crate) fn get_file_name(rustc: &Path, crate_name: &str, crate_type: &str) -> String {
|
||||
let file_name = Command::new(rustc)
|
||||
.stderr(Stdio::inherit())
|
||||
.args(&[
|
||||
.args([
|
||||
"--crate-name",
|
||||
crate_name,
|
||||
"--crate-type",
|
||||
|
|
|
|||
|
|
@ -89,15 +89,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
|
|||
TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]),
|
||||
TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"),
|
||||
TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]),
|
||||
TestCase::custom("aot.gen_block_iterate", &|runner| {
|
||||
runner.run_rustc([
|
||||
"example/gen_block_iterate.rs",
|
||||
"--edition",
|
||||
"2024",
|
||||
"-Zunstable-options",
|
||||
]);
|
||||
runner.run_out_command("gen_block_iterate", &[]);
|
||||
}),
|
||||
TestCase::build_bin_and_run("aot.gen_block_iterate", "example/gen_block_iterate.rs", &[]),
|
||||
TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]),
|
||||
TestCase::custom("test.sysroot", &|runner| {
|
||||
apply_patches(
|
||||
|
|
@ -217,13 +209,15 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
|
|||
|
||||
PORTABLE_SIMD.clean(&runner.dirs);
|
||||
|
||||
let mut build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
|
||||
build_cmd.arg("--all-targets");
|
||||
let build_cmd = PORTABLE_SIMD.build(&runner.target_compiler, &runner.dirs);
|
||||
// FIXME uncomment once examples work: https://github.com/rust-lang/portable-simd/issues/470
|
||||
//build_cmd.arg("--all-targets");
|
||||
spawn_and_wait(build_cmd);
|
||||
|
||||
if runner.is_native {
|
||||
let mut test_cmd = PORTABLE_SIMD.test(&runner.target_compiler, &runner.dirs);
|
||||
test_cmd.arg("-q");
|
||||
// FIXME remove --tests once examples work: https://github.com/rust-lang/portable-simd/issues/470
|
||||
test_cmd.arg("-q").arg("--tests");
|
||||
spawn_and_wait(test_cmd);
|
||||
}
|
||||
}),
|
||||
|
|
@ -233,6 +227,7 @@ pub(crate) fn run_tests(
|
|||
dirs: &Dirs,
|
||||
sysroot_kind: SysrootKind,
|
||||
use_unstable_features: bool,
|
||||
panic_unwind_support: bool,
|
||||
skip_tests: &[&str],
|
||||
cg_clif_dylib: &CodegenBackend,
|
||||
bootstrap_host_compiler: &Compiler,
|
||||
|
|
@ -251,12 +246,14 @@ pub(crate) fn run_tests(
|
|||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
target_triple.clone(),
|
||||
panic_unwind_support,
|
||||
);
|
||||
|
||||
let runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
use_unstable_features,
|
||||
panic_unwind_support,
|
||||
skip_tests,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
stdlib_source.clone(),
|
||||
|
|
@ -283,12 +280,14 @@ pub(crate) fn run_tests(
|
|||
bootstrap_host_compiler,
|
||||
rustup_toolchain_name,
|
||||
target_triple.clone(),
|
||||
panic_unwind_support,
|
||||
);
|
||||
|
||||
let mut runner = TestRunner::new(
|
||||
dirs.clone(),
|
||||
target_compiler,
|
||||
use_unstable_features,
|
||||
panic_unwind_support,
|
||||
skip_tests,
|
||||
bootstrap_host_compiler.triple == target_triple,
|
||||
stdlib_source,
|
||||
|
|
@ -314,6 +313,7 @@ pub(crate) fn run_tests(
|
|||
struct TestRunner<'a> {
|
||||
is_native: bool,
|
||||
jit_supported: bool,
|
||||
panic_unwind_support: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
dirs: Dirs,
|
||||
target_compiler: Compiler,
|
||||
|
|
@ -325,6 +325,7 @@ impl<'a> TestRunner<'a> {
|
|||
dirs: Dirs,
|
||||
mut target_compiler: Compiler,
|
||||
use_unstable_features: bool,
|
||||
panic_unwind_support: bool,
|
||||
skip_tests: &'a [&'a str],
|
||||
is_native: bool,
|
||||
stdlib_source: PathBuf,
|
||||
|
|
@ -335,7 +336,15 @@ impl<'a> TestRunner<'a> {
|
|||
let jit_supported =
|
||||
use_unstable_features && is_native && !target_compiler.triple.contains("windows");
|
||||
|
||||
Self { is_native, jit_supported, skip_tests, dirs, target_compiler, stdlib_source }
|
||||
Self {
|
||||
is_native,
|
||||
jit_supported,
|
||||
panic_unwind_support,
|
||||
skip_tests,
|
||||
dirs,
|
||||
target_compiler,
|
||||
stdlib_source,
|
||||
}
|
||||
}
|
||||
|
||||
fn run_testsuite(&self, tests: &[TestCase]) {
|
||||
|
|
@ -346,7 +355,7 @@ impl<'a> TestRunner<'a> {
|
|||
|
||||
let _guard = if !config::get_bool(config)
|
||||
|| (is_jit_test && !self.jit_supported)
|
||||
|| self.skip_tests.contains(&config)
|
||||
|| self.skip_tests.contains(config)
|
||||
{
|
||||
eprintln!("[{tag}] {testname} (skipped)");
|
||||
continue;
|
||||
|
|
@ -404,8 +413,11 @@ impl<'a> TestRunner<'a> {
|
|||
cmd.arg("-Cdebuginfo=2");
|
||||
cmd.arg("--target");
|
||||
cmd.arg(&self.target_compiler.triple);
|
||||
cmd.arg("-Cpanic=abort");
|
||||
if !self.panic_unwind_support {
|
||||
cmd.arg("-Cpanic=abort");
|
||||
}
|
||||
cmd.arg("--check-cfg=cfg(jit)");
|
||||
cmd.arg("--edition=2024");
|
||||
cmd.args(args);
|
||||
cmd
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ OPTIONS:
|
|||
Some features are not yet ready for production usage. This option will disable these
|
||||
features. This includes the JIT mode and inline assembly support.
|
||||
|
||||
--panic-unwind-support
|
||||
Enable support for unwinding when -Cpanic=unwind is used. This currently regresses build
|
||||
performance.
|
||||
|
||||
--frozen
|
||||
Require Cargo.lock and cache are up to date
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ impl CargoProject {
|
|||
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
|
||||
let src = src.as_ref();
|
||||
let dst = dst.as_ref();
|
||||
if let Err(_) = fs::hard_link(src, dst) {
|
||||
if fs::hard_link(src, dst).is_err() {
|
||||
fs::copy(src, dst).unwrap(); // Fallback to copying if hardlinking failed
|
||||
}
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ pub(crate) fn spawn_and_wait(mut cmd: Command) {
|
|||
/// Create the specified directory if it doesn't exist yet and delete all contents.
|
||||
pub(crate) fn ensure_empty_dir(path: &Path) {
|
||||
fs::create_dir_all(path).unwrap();
|
||||
let read_dir = match fs::read_dir(&path) {
|
||||
let read_dir = match fs::read_dir(path) {
|
||||
Ok(read_dir) => read_dir,
|
||||
Err(err) if err.kind() == io::ErrorKind::NotFound => {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ aot.mini_core_hello_world
|
|||
|
||||
testsuite.base_sysroot
|
||||
aot.arbitrary_self_types_pointers_and_wrappers
|
||||
aot.issue_91827_extern_types
|
||||
jit.std_example
|
||||
aot.std_example
|
||||
aot.dst_field_align
|
||||
|
|
|
|||
|
|
@ -77,12 +77,16 @@ pub fn use_size_of() -> usize {
|
|||
}
|
||||
|
||||
pub unsafe fn use_copy_intrinsic(src: *const u8, dst: *mut u8) {
|
||||
intrinsics::copy::<u8>(src, dst, 1);
|
||||
unsafe {
|
||||
intrinsics::copy::<u8>(src, dst, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn use_copy_intrinsic_ref(src: *const u8, dst: *mut u8) {
|
||||
let copy2 = &intrinsics::copy::<u8>;
|
||||
copy2(src, dst, 1);
|
||||
unsafe {
|
||||
let copy2 = &intrinsics::copy::<u8>;
|
||||
copy2(src, dst, 1);
|
||||
}
|
||||
}
|
||||
|
||||
pub const ABC: u8 = 6 * 7;
|
||||
|
|
@ -126,11 +130,11 @@ pub fn eq_char(a: char, b: char) -> bool {
|
|||
}
|
||||
|
||||
pub unsafe fn transmute(c: char) -> u32 {
|
||||
intrinsics::transmute(c)
|
||||
unsafe { intrinsics::transmute(c) }
|
||||
}
|
||||
|
||||
pub unsafe fn deref_str_ptr(s: *const str) -> &'static str {
|
||||
&*s
|
||||
unsafe { &*s }
|
||||
}
|
||||
|
||||
pub fn use_array(arr: [u8; 3]) -> u8 {
|
||||
|
|
@ -146,7 +150,7 @@ pub fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
|
|||
}
|
||||
|
||||
pub unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
|
||||
intrinsics::ctlz_nonzero(a)
|
||||
unsafe { intrinsics::ctlz_nonzero(a) }
|
||||
}
|
||||
|
||||
pub fn ptr_as_usize(ptr: *const u8) -> usize {
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ fn panic_in_cleanup() -> ! {
|
|||
|
||||
#[cfg(all(unix, not(target_vendor = "apple")))]
|
||||
#[link(name = "gcc_s")]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn _Unwind_Resume(exc: *mut ()) -> !;
|
||||
}
|
||||
|
||||
|
|
@ -555,7 +555,9 @@ extern "C" {
|
|||
pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
// Code here does not matter - this is replaced by the
|
||||
// real drop glue by the compiler.
|
||||
drop_in_place(to_drop);
|
||||
unsafe {
|
||||
drop_in_place(to_drop);
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "unpin"]
|
||||
|
|
@ -622,7 +624,7 @@ impl<T: ?Sized> Deref for Box<T> {
|
|||
|
||||
#[lang = "exchange_malloc"]
|
||||
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
libc::malloc(size)
|
||||
unsafe { libc::malloc(size) }
|
||||
}
|
||||
|
||||
#[lang = "drop"]
|
||||
|
|
@ -649,11 +651,11 @@ pub mod intrinsics {
|
|||
#[rustc_intrinsic]
|
||||
pub const fn size_of<T>() -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
pub unsafe fn size_of_val<T: ?crate::Sized>(val: *const T) -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub const fn align_of<T>() -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn align_of_val<T: ?::Sized>(val: *const T) -> usize;
|
||||
pub unsafe fn align_of_val<T: ?crate::Sized>(val: *const T) -> usize;
|
||||
#[rustc_intrinsic]
|
||||
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
#[rustc_intrinsic]
|
||||
|
|
@ -661,7 +663,7 @@ pub mod intrinsics {
|
|||
#[rustc_intrinsic]
|
||||
pub unsafe fn ctlz_nonzero<T>(x: T) -> u32;
|
||||
#[rustc_intrinsic]
|
||||
pub const fn needs_drop<T: ?::Sized>() -> bool;
|
||||
pub const fn needs_drop<T: ?crate::Sized>() -> bool;
|
||||
#[rustc_intrinsic]
|
||||
pub fn bitreverse<T>(x: T) -> T;
|
||||
#[rustc_intrinsic]
|
||||
|
|
@ -678,13 +680,13 @@ pub mod libc {
|
|||
// symbols to link against.
|
||||
#[cfg_attr(unix, link(name = "c"))]
|
||||
#[cfg_attr(target_env = "msvc", link(name = "legacy_stdio_definitions"))]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
pub fn printf(format: *const i8, ...) -> i32;
|
||||
}
|
||||
|
||||
#[cfg_attr(unix, link(name = "c"))]
|
||||
#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
pub fn puts(s: *const i8) -> i32;
|
||||
pub fn malloc(size: usize) -> *mut u8;
|
||||
pub fn free(ptr: *mut u8);
|
||||
|
|
@ -733,7 +735,7 @@ trait SizedTypeProperties: Sized {
|
|||
}
|
||||
impl<T> SizedTypeProperties for T {}
|
||||
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
type VaListImpl;
|
||||
}
|
||||
|
||||
|
|
@ -792,7 +794,7 @@ struct PanicLocation {
|
|||
column: u32,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
#[cfg(not(all(windows, target_env = "gnu")))]
|
||||
pub fn get_tls() -> u8 {
|
||||
#[thread_local]
|
||||
|
|
|
|||
|
|
@ -124,9 +124,11 @@ static mut NUM: u8 = 6 * 7;
|
|||
static NUM_REF: &'static u8 = unsafe { &*&raw const NUM };
|
||||
|
||||
unsafe fn zeroed<T>() -> T {
|
||||
let mut uninit = MaybeUninit { uninit: () };
|
||||
intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1);
|
||||
uninit.value.value
|
||||
unsafe {
|
||||
let mut uninit = MaybeUninit { uninit: () };
|
||||
intrinsics::write_bytes(&mut uninit.value.value as *mut T, 0, 1);
|
||||
uninit.value.value
|
||||
}
|
||||
}
|
||||
|
||||
fn take_f32(_f: f32) {}
|
||||
|
|
@ -237,7 +239,7 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe fn uninitialized<T>() -> T {
|
||||
MaybeUninit { uninit: () }.value.value
|
||||
unsafe { MaybeUninit { uninit: () }.value.value }
|
||||
}
|
||||
|
||||
zeroed::<(u8, u8)>();
|
||||
|
|
@ -270,20 +272,20 @@ fn main() {
|
|||
let x = &[0u32, 42u32] as &[u32];
|
||||
match x {
|
||||
[] => assert_eq!(0u32, 1),
|
||||
[_, ref y @ ..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
|
||||
[_, y @ ..] => assert_eq!(&x[1] as *const u32 as usize, &y[0] as *const u32 as usize),
|
||||
}
|
||||
|
||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
||||
|
||||
#[cfg(not(any(jit, target_vendor = "apple", windows)))]
|
||||
{
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
#[linkage = "extern_weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
||||
{
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
#[linkage = "extern_weak"]
|
||||
static ABC: *const u8;
|
||||
}
|
||||
|
|
@ -310,7 +312,7 @@ fn main() {
|
|||
|
||||
check_niche_behavior();
|
||||
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
type ExternType;
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +366,7 @@ fn stack_val_align() {
|
|||
}
|
||||
|
||||
#[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "macos")))]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn global_asm_test();
|
||||
}
|
||||
|
||||
|
|
@ -412,7 +414,7 @@ struct pthread_attr_t {
|
|||
|
||||
#[link(name = "pthread")]
|
||||
#[cfg(unix)]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int;
|
||||
|
||||
fn pthread_create(
|
||||
|
|
@ -433,7 +435,7 @@ type HANDLE = *mut c_void;
|
|||
|
||||
#[link(name = "msvcrt")]
|
||||
#[cfg(windows)]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn WaitForSingleObject(hHandle: LPVOID, dwMilliseconds: DWORD) -> DWORD;
|
||||
|
||||
fn CreateThread(
|
||||
|
|
@ -455,46 +457,51 @@ struct Thread {
|
|||
|
||||
impl Thread {
|
||||
unsafe fn create(f: extern "C" fn(_: *mut c_void) -> *mut c_void) -> Self {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let mut attr: pthread_attr_t = zeroed();
|
||||
let mut thread: pthread_t = 0;
|
||||
unsafe {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let mut attr: pthread_attr_t = zeroed();
|
||||
let mut thread: pthread_t = 0;
|
||||
|
||||
if pthread_attr_init(&mut attr) != 0 {
|
||||
assert!(false);
|
||||
if pthread_attr_init(&mut attr) != 0 {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
Thread { handle: thread }
|
||||
}
|
||||
|
||||
if pthread_create(&mut thread, &attr, f, 0 as *mut c_void) != 0 {
|
||||
assert!(false);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let handle =
|
||||
CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32);
|
||||
|
||||
if (handle as u64) == 0 {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
Thread { handle }
|
||||
}
|
||||
|
||||
Thread { handle: thread }
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let handle = CreateThread(0 as *mut c_void, 0, f, 0 as *mut c_void, 0, 0 as *mut u32);
|
||||
|
||||
if (handle as u64) == 0 {
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
Thread { handle }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn join(self) {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let mut res = 0 as *mut c_void;
|
||||
pthread_join(self.handle, &mut res);
|
||||
}
|
||||
unsafe {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let mut res = 0 as *mut c_void;
|
||||
pthread_join(self.handle, &mut res);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// The INFINITE macro is used to signal operations that do not timeout.
|
||||
let infinite = 0xffffffff;
|
||||
assert!(WaitForSingleObject(self.handle, infinite) == 0);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
// The INFINITE macro is used to signal operations that do not timeout.
|
||||
let infinite = 0xffffffff;
|
||||
assert!(WaitForSingleObject(self.handle, infinite) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ unsafe fn test_vpmin_s8() {
|
|||
let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]);
|
||||
let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
|
||||
let e = i8x8::from([-2, -4, 5, 7, 0, 2, 4, 6]);
|
||||
let r: i8x8 = transmute(vpmin_s8(transmute(a), transmute(b)));
|
||||
let r: i8x8 = unsafe { transmute(vpmin_s8(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ unsafe fn test_vpmin_s16() {
|
|||
let a = i16x4::from([1, 2, 3, -4]);
|
||||
let b = i16x4::from([0, 3, 2, 5]);
|
||||
let e = i16x4::from([1, -4, 0, 2]);
|
||||
let r: i16x4 = transmute(vpmin_s16(transmute(a), transmute(b)));
|
||||
let r: i16x4 = unsafe { transmute(vpmin_s16(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ unsafe fn test_vpmin_s32() {
|
|||
let a = i32x2::from([1, -2]);
|
||||
let b = i32x2::from([0, 3]);
|
||||
let e = i32x2::from([-2, 0]);
|
||||
let r: i32x2 = transmute(vpmin_s32(transmute(a), transmute(b)));
|
||||
let r: i32x2 = unsafe { transmute(vpmin_s32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ unsafe fn test_vpmin_u8() {
|
|||
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
|
||||
let e = u8x8::from([1, 3, 5, 7, 0, 2, 4, 6]);
|
||||
let r: u8x8 = transmute(vpmin_u8(transmute(a), transmute(b)));
|
||||
let r: u8x8 = unsafe { transmute(vpmin_u8(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ unsafe fn test_vpmin_u16() {
|
|||
let a = u16x4::from([1, 2, 3, 4]);
|
||||
let b = u16x4::from([0, 3, 2, 5]);
|
||||
let e = u16x4::from([1, 3, 0, 2]);
|
||||
let r: u16x4 = transmute(vpmin_u16(transmute(a), transmute(b)));
|
||||
let r: u16x4 = unsafe { transmute(vpmin_u16(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ unsafe fn test_vpmin_u32() {
|
|||
let a = u32x2::from([1, 2]);
|
||||
let b = u32x2::from([0, 3]);
|
||||
let e = u32x2::from([1, 0]);
|
||||
let r: u32x2 = transmute(vpmin_u32(transmute(a), transmute(b)));
|
||||
let r: u32x2 = unsafe { transmute(vpmin_u32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ unsafe fn test_vpmin_f32() {
|
|||
let a = f32x2::from([1., -2.]);
|
||||
let b = f32x2::from([0., 3.]);
|
||||
let e = f32x2::from([-2., 0.]);
|
||||
let r: f32x2 = transmute(vpmin_f32(transmute(a), transmute(b)));
|
||||
let r: f32x2 = unsafe { transmute(vpmin_f32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ unsafe fn test_vpmax_s8() {
|
|||
let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]);
|
||||
let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
|
||||
let e = i8x8::from([1, 3, 6, 8, 3, 5, 7, 9]);
|
||||
let r: i8x8 = transmute(vpmax_s8(transmute(a), transmute(b)));
|
||||
let r: i8x8 = unsafe { transmute(vpmax_s8(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ unsafe fn test_vpmax_s16() {
|
|||
let a = i16x4::from([1, 2, 3, -4]);
|
||||
let b = i16x4::from([0, 3, 2, 5]);
|
||||
let e = i16x4::from([2, 3, 3, 5]);
|
||||
let r: i16x4 = transmute(vpmax_s16(transmute(a), transmute(b)));
|
||||
let r: i16x4 = unsafe { transmute(vpmax_s16(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ unsafe fn test_vpmax_s32() {
|
|||
let a = i32x2::from([1, -2]);
|
||||
let b = i32x2::from([0, 3]);
|
||||
let e = i32x2::from([1, 3]);
|
||||
let r: i32x2 = transmute(vpmax_s32(transmute(a), transmute(b)));
|
||||
let r: i32x2 = unsafe { transmute(vpmax_s32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ unsafe fn test_vpmax_u8() {
|
|||
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]);
|
||||
let e = u8x8::from([2, 4, 6, 8, 3, 5, 7, 9]);
|
||||
let r: u8x8 = transmute(vpmax_u8(transmute(a), transmute(b)));
|
||||
let r: u8x8 = unsafe { transmute(vpmax_u8(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ unsafe fn test_vpmax_u16() {
|
|||
let a = u16x4::from([1, 2, 3, 4]);
|
||||
let b = u16x4::from([0, 3, 2, 5]);
|
||||
let e = u16x4::from([2, 4, 3, 5]);
|
||||
let r: u16x4 = transmute(vpmax_u16(transmute(a), transmute(b)));
|
||||
let r: u16x4 = unsafe { transmute(vpmax_u16(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ unsafe fn test_vpmax_u32() {
|
|||
let a = u32x2::from([1, 2]);
|
||||
let b = u32x2::from([0, 3]);
|
||||
let e = u32x2::from([2, 3]);
|
||||
let r: u32x2 = transmute(vpmax_u32(transmute(a), transmute(b)));
|
||||
let r: u32x2 = unsafe { transmute(vpmax_u32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ unsafe fn test_vpmax_f32() {
|
|||
let a = f32x2::from([1., -2.]);
|
||||
let b = f32x2::from([0., 3.]);
|
||||
let e = f32x2::from([1., 3.]);
|
||||
let r: f32x2 = transmute(vpmax_f32(transmute(a), transmute(b)));
|
||||
let r: f32x2 = unsafe { transmute(vpmax_f32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ unsafe fn test_vpmax_f32() {
|
|||
unsafe fn test_vpadd_s16() {
|
||||
let a = i16x4::from([1, 2, 3, 4]);
|
||||
let b = i16x4::from([0, -1, -2, -3]);
|
||||
let r: i16x4 = transmute(vpadd_s16(transmute(a), transmute(b)));
|
||||
let r: i16x4 = unsafe { transmute(vpadd_s16(transmute(a), transmute(b))) };
|
||||
let e = i16x4::from([3, 7, -1, -5]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -147,7 +147,7 @@ unsafe fn test_vpadd_s16() {
|
|||
unsafe fn test_vpadd_s32() {
|
||||
let a = i32x2::from([1, 2]);
|
||||
let b = i32x2::from([0, -1]);
|
||||
let r: i32x2 = transmute(vpadd_s32(transmute(a), transmute(b)));
|
||||
let r: i32x2 = unsafe { transmute(vpadd_s32(transmute(a), transmute(b))) };
|
||||
let e = i32x2::from([3, -1]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ unsafe fn test_vpadd_s32() {
|
|||
unsafe fn test_vpadd_s8() {
|
||||
let a = i8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let b = i8x8::from([0, -1, -2, -3, -4, -5, -6, -7]);
|
||||
let r: i8x8 = transmute(vpadd_s8(transmute(a), transmute(b)));
|
||||
let r: i8x8 = unsafe { transmute(vpadd_s8(transmute(a), transmute(b))) };
|
||||
let e = i8x8::from([3, 7, 11, 15, -1, -5, -9, -13]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ unsafe fn test_vpadd_s8() {
|
|||
unsafe fn test_vpadd_u16() {
|
||||
let a = u16x4::from([1, 2, 3, 4]);
|
||||
let b = u16x4::from([30, 31, 32, 33]);
|
||||
let r: u16x4 = transmute(vpadd_u16(transmute(a), transmute(b)));
|
||||
let r: u16x4 = unsafe { transmute(vpadd_u16(transmute(a), transmute(b))) };
|
||||
let e = u16x4::from([3, 7, 61, 65]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -171,7 +171,7 @@ unsafe fn test_vpadd_u16() {
|
|||
unsafe fn test_vpadd_u32() {
|
||||
let a = u32x2::from([1, 2]);
|
||||
let b = u32x2::from([30, 31]);
|
||||
let r: u32x2 = transmute(vpadd_u32(transmute(a), transmute(b)));
|
||||
let r: u32x2 = unsafe { transmute(vpadd_u32(transmute(a), transmute(b))) };
|
||||
let e = u32x2::from([3, 61]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ unsafe fn test_vpadd_u32() {
|
|||
unsafe fn test_vpadd_u8() {
|
||||
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let b = u8x8::from([30, 31, 32, 33, 34, 35, 36, 37]);
|
||||
let r: u8x8 = transmute(vpadd_u8(transmute(a), transmute(b)));
|
||||
let r: u8x8 = unsafe { transmute(vpadd_u8(transmute(a), transmute(b))) };
|
||||
let e = u8x8::from([3, 7, 11, 15, 61, 65, 69, 73]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -188,7 +188,7 @@ unsafe fn test_vpadd_u8() {
|
|||
unsafe fn test_vqsub_u8() {
|
||||
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]);
|
||||
let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]);
|
||||
let r: u8x8 = transmute(vqsub_u8(transmute(a), transmute(b)));
|
||||
let r: u8x8 = unsafe { transmute(vqsub_u8(transmute(a), transmute(b))) };
|
||||
let e = u8x8::from([0, 1, 2, 3, 0, 0, 0, 218]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ unsafe fn test_vqsub_u8() {
|
|||
unsafe fn test_vqadd_u8() {
|
||||
let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]);
|
||||
let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]);
|
||||
let r: u8x8 = transmute(vqadd_u8(transmute(a), transmute(b)));
|
||||
let r: u8x8 = unsafe { transmute(vqadd_u8(transmute(a), transmute(b))) };
|
||||
let e = u8x8::from([31, 3, 4, 5, 39, 0xff, 43, 0xff]);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
|
@ -208,7 +208,7 @@ unsafe fn test_vmaxq_f32() {
|
|||
let a = f32x4::from([0., -1., 2., -3.]);
|
||||
let b = f32x4::from([-4., 5., -6., 7.]);
|
||||
let e = f32x4::from([0., 5., 2., 7.]);
|
||||
let r: f32x4 = transmute(vmaxq_f32(transmute(a), transmute(b)));
|
||||
let r: f32x4 = unsafe { transmute(vmaxq_f32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ unsafe fn test_vminq_f32() {
|
|||
let a = f32x4::from([0., -1., 2., -3.]);
|
||||
let b = f32x4::from([-4., 5., -6., 7.]);
|
||||
let e = f32x4::from([-4., -1., -6., -3.]);
|
||||
let r: f32x4 = transmute(vminq_f32(transmute(a), transmute(b)));
|
||||
let r: f32x4 = unsafe { transmute(vminq_f32(transmute(a), transmute(b))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ unsafe fn test_vaddvq_f32() {
|
|||
// AArch64 llvm intrinsic: llvm.aarch64.neon.faddv.f32.v4f32
|
||||
let a = f32x4::from([0., 1., 2., 3.]);
|
||||
let e = 6f32;
|
||||
let r = vaddvq_f32(transmute(a));
|
||||
let r = unsafe { vaddvq_f32(transmute(a)) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ unsafe fn test_vrndnq_f32() {
|
|||
// llvm intrinsic: llvm.roundeven.v4f32
|
||||
let a = f32x4::from([0.1, -1.9, 4.5, 5.5]);
|
||||
let e = f32x4::from([0., -2., 4., 6.]);
|
||||
let r: f32x4 = transmute(vrndnq_f32(transmute(a)));
|
||||
let r: f32x4 = unsafe { transmute(vrndnq_f32(transmute(a))) };
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ fn main() {
|
|||
#[cfg(windows)]
|
||||
{
|
||||
#[link(name = "kernel32", kind = "raw-dylib")]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn GetModuleFileNameA(
|
||||
module: *mut std::ffi::c_void,
|
||||
filename: *mut u8,
|
||||
|
|
|
|||
|
|
@ -230,51 +230,53 @@ unsafe fn test_crc32() {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_simd() {
|
||||
assert!(is_x86_feature_detected!("sse2"));
|
||||
unsafe {
|
||||
assert!(is_x86_feature_detected!("sse2"));
|
||||
|
||||
let x = _mm_setzero_si128();
|
||||
let y = _mm_set1_epi16(7);
|
||||
let or = _mm_or_si128(x, y);
|
||||
let cmp_eq = _mm_cmpeq_epi8(y, y);
|
||||
let cmp_lt = _mm_cmplt_epi8(y, y);
|
||||
let x = _mm_setzero_si128();
|
||||
let y = _mm_set1_epi16(7);
|
||||
let or = _mm_or_si128(x, y);
|
||||
let cmp_eq = _mm_cmpeq_epi8(y, y);
|
||||
let cmp_lt = _mm_cmplt_epi8(y, y);
|
||||
|
||||
let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
|
||||
assert_eq!((zero0, zero1), (0, 0));
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
|
||||
assert_eq!(
|
||||
std::mem::transmute::<_, [u16; 8]>(cmp_eq),
|
||||
[0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]
|
||||
);
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x);
|
||||
assert_eq!((zero0, zero1), (0, 0));
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]);
|
||||
assert_eq!(
|
||||
std::mem::transmute::<_, [u16; 8]>(cmp_eq),
|
||||
[0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]
|
||||
);
|
||||
assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
|
||||
test_mm_slli_si128();
|
||||
test_mm_movemask_epi8();
|
||||
test_mm256_movemask_epi8();
|
||||
test_mm_add_epi8();
|
||||
test_mm_add_pd();
|
||||
test_mm_cvtepi8_epi16();
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cvtps_epi32();
|
||||
test_mm_cvttps_epi32();
|
||||
test_mm_cvtsi128_si64();
|
||||
test_mm_slli_si128();
|
||||
test_mm_movemask_epi8();
|
||||
test_mm256_movemask_epi8();
|
||||
test_mm_add_epi8();
|
||||
test_mm_add_pd();
|
||||
test_mm_cvtepi8_epi16();
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cvtps_epi32();
|
||||
test_mm_cvttps_epi32();
|
||||
test_mm_cvtsi128_si64();
|
||||
|
||||
test_mm_extract_epi8();
|
||||
test_mm_insert_epi16();
|
||||
test_mm_shuffle_epi8();
|
||||
test_mm_extract_epi8();
|
||||
test_mm_insert_epi16();
|
||||
test_mm_shuffle_epi8();
|
||||
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cmpestri();
|
||||
#[cfg(not(jit))]
|
||||
test_mm_cmpestri();
|
||||
|
||||
test_mm256_shuffle_epi8();
|
||||
test_mm256_permute2x128_si256();
|
||||
test_mm256_permutevar8x32_epi32();
|
||||
test_mm256_shuffle_epi8();
|
||||
test_mm256_permute2x128_si256();
|
||||
test_mm256_permutevar8x32_epi32();
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[rustfmt::skip]
|
||||
let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)));
|
||||
assert_eq!(mask1, 1);
|
||||
assert_eq!(mask1, 1);
|
||||
|
||||
#[cfg(not(jit))]
|
||||
test_crc32();
|
||||
#[cfg(not(jit))]
|
||||
test_crc32();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
|
@ -361,7 +363,7 @@ fn assert_eq_m128i(x: std::arch::x86_64::__m128i, y: std::arch::x86_64::__m128i)
|
|||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
pub fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
||||
if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
|
||||
panic!("{:?} != {:?}", a, b);
|
||||
}
|
||||
|
|
@ -369,15 +371,19 @@ pub unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
|
|||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx")]
|
||||
pub unsafe fn assert_eq_m256i(a: __m256i, b: __m256i) {
|
||||
assert_eq!(std::mem::transmute::<_, [u64; 4]>(a), std::mem::transmute::<_, [u64; 4]>(b))
|
||||
pub fn assert_eq_m256i(a: __m256i, b: __m256i) {
|
||||
unsafe {
|
||||
assert_eq!(std::mem::transmute::<_, [u64; 4]>(a), std::mem::transmute::<_, [u64; 4]>(b))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn test_mm_cvtsi128_si64() {
|
||||
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
|
||||
assert_eq!(r, 5);
|
||||
unsafe {
|
||||
let r = _mm_cvtsi128_si64(std::mem::transmute::<[i64; 2], _>([5, 0]));
|
||||
assert_eq!(r, 5);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
|
@ -445,20 +451,24 @@ unsafe fn test_mm_shuffle_epi8() {
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse4.2")]
|
||||
unsafe fn str_to_m128i(s: &[u8]) -> __m128i {
|
||||
assert!(s.len() <= 16);
|
||||
let slice = &mut [0u8; 16];
|
||||
std::ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
|
||||
_mm_loadu_si128(slice.as_ptr() as *const _)
|
||||
unsafe {
|
||||
assert!(s.len() <= 16);
|
||||
let slice = &mut [0u8; 16];
|
||||
std::ptr::copy_nonoverlapping(s.as_ptr(), slice.as_mut_ptr(), s.len());
|
||||
_mm_loadu_si128(slice.as_ptr() as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(jit))]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse4.2")]
|
||||
unsafe fn test_mm_cmpestri() {
|
||||
let a = str_to_m128i(b"bar - garbage");
|
||||
let b = str_to_m128i(b"foobar");
|
||||
let i = _mm_cmpestri::<_SIDD_CMP_EQUAL_ORDERED>(a, 3, b, 6);
|
||||
assert_eq!(3, i);
|
||||
unsafe {
|
||||
let a = str_to_m128i(b"bar - garbage");
|
||||
let b = str_to_m128i(b"foobar");
|
||||
let i = _mm_cmpestri::<_SIDD_CMP_EQUAL_ORDERED>(a, 3, b, 6);
|
||||
assert_eq!(3, i);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
|
@ -513,35 +523,39 @@ unsafe fn test_mm256_permutevar8x32_epi32() {
|
|||
#[target_feature(enable = "avx2")]
|
||||
#[cfg(not(jit))]
|
||||
unsafe fn test_mm_cvtps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
unsafe {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvtps_epi32(float_vec);
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvtps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [2, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn test_mm_cvttps_epi32() {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
unsafe {
|
||||
let floats: [f32; 4] = [1.5, -2.5, i32::MAX as f32 + 1.0, f32::NAN];
|
||||
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvttps_epi32(float_vec);
|
||||
let float_vec = _mm_loadu_ps(floats.as_ptr());
|
||||
let int_vec = _mm_cvttps_epi32(float_vec);
|
||||
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
let mut ints: [i32; 4] = [0; 4];
|
||||
_mm_storeu_si128(ints.as_mut_ptr() as *mut __m128i, int_vec);
|
||||
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
|
||||
// this is very different from `floats.map(|f| f as i32)`!
|
||||
let expected_ints: [i32; 4] = [1, -2, i32::MIN, i32::MIN];
|
||||
|
||||
assert_eq!(ints, expected_ints);
|
||||
assert_eq!(ints, expected_ints);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_checked_mul() {
|
||||
|
|
|
|||
|
|
@ -11,38 +11,41 @@ diff --git a/coretests/tests/slice.rs b/coretests/tests/slice.rs
|
|||
index 8402833..84592e0 100644
|
||||
--- a/coretests/tests/slice.rs
|
||||
+++ b/coretests/tests/slice.rs
|
||||
@@ -1809,6 +1809,7 @@ fn sort_unstable() {
|
||||
}
|
||||
}
|
||||
@@ -1619,7 +1619,7 @@ fn brute_force_rotate_test_1() {
|
||||
|
||||
+/*
|
||||
#[test]
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
@@ -1914,6 +1915,7 @@ fn select_nth_unstable() {
|
||||
v.select_nth_unstable(0);
|
||||
assert!(v == [0xDEADBEEF]);
|
||||
}
|
||||
+*/
|
||||
-#[cfg_attr(miri, ignore)] // Miri is too slow
|
||||
+#[ignore] // Miri is too slow
|
||||
fn select_nth_unstable() {
|
||||
use core::cmp::Ordering::{Equal, Greater, Less};
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "index 0 greater than length of slice")]
|
||||
@@ -2462,6 +2462,7 @@ take_tests! {
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
@@ -2303,14 +2303,14 @@ split_off_tests! {
|
||||
const EMPTY_MAX: &'static [()] = &[(); usize::MAX];
|
||||
|
||||
+/*
|
||||
// can't be a constant due to const mutability rules
|
||||
#[cfg(not(miri))] // unused in Miri
|
||||
-#[cfg(not(miri))] // unused in Miri
|
||||
+#[cfg(any())] // unused in Miri
|
||||
macro_rules! empty_max_mut {
|
||||
@@ -2485,6 +2486,7 @@ take_tests! {
|
||||
(split_off_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(split_off_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
() => {
|
||||
&mut [(); usize::MAX] as _
|
||||
};
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn test_slice_from_ptr_range() {
|
||||
-#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
|
||||
+#[cfg(any())] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
|
||||
split_off_tests! {
|
||||
slice: &[(); usize::MAX], method: split_off,
|
||||
(split_off_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]),
|
||||
@@ -2318,7 +2318,7 @@ split_off_tests! {
|
||||
(split_off_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX),
|
||||
}
|
||||
|
||||
-#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
|
||||
+#[cfg(any())] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
|
||||
split_off_tests! {
|
||||
slice: &mut [(); usize::MAX], method: split_off_mut,
|
||||
(split_off_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]),
|
||||
diff --git a/alloctests/tests/sort/tests.rs b/alloctests/tests/sort/tests.rs
|
||||
index d321f8d..8b2040a 100644
|
||||
--- a/alloctests/tests/sort/tests.rs
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-06-24"
|
||||
channel = "nightly-2025-11-08"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
profile = "minimal"
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ fn main() {
|
|||
sysroot = sysroot.parent().unwrap();
|
||||
}
|
||||
|
||||
let mut rustflags = vec!["-Cpanic=abort".to_owned(), "-Zpanic-abort-tests".to_owned()];
|
||||
let mut rustflags = vec![];
|
||||
if !cfg!(support_panic_unwind) {
|
||||
rustflags.push("-Cpanic=abort".to_owned());
|
||||
rustflags.push("-Zpanic-abort-tests".to_owned());
|
||||
}
|
||||
if let Some(name) = option_env!("BUILTIN_BACKEND") {
|
||||
rustflags.push(format!("-Zcodegen-backend={name}"));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ fn main() {
|
|||
|
||||
let passed_args = std::env::args_os().skip(1).collect::<Vec<_>>();
|
||||
let mut args = vec![];
|
||||
args.push(OsString::from("-Cpanic=abort"));
|
||||
args.push(OsString::from("-Zpanic-abort-tests"));
|
||||
if !cfg!(support_panic_unwind) {
|
||||
args.push(OsString::from("-Cpanic=abort"));
|
||||
args.push(OsString::from("-Zpanic-abort-tests"));
|
||||
}
|
||||
if let Some(name) = option_env!("BUILTIN_BACKEND") {
|
||||
args.push(OsString::from(format!("-Zcodegen-backend={name}")))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ fn main() {
|
|||
|
||||
let passed_args = std::env::args_os().skip(1).collect::<Vec<_>>();
|
||||
let mut args = vec![];
|
||||
args.push(OsString::from("-Cpanic=abort"));
|
||||
args.push(OsString::from("-Zpanic-abort-tests"));
|
||||
if !cfg!(support_panic_unwind) {
|
||||
args.push(OsString::from("-Cpanic=abort"));
|
||||
args.push(OsString::from("-Zpanic-abort-tests"));
|
||||
}
|
||||
if let Some(name) = option_env!("BUILTIN_BACKEND") {
|
||||
args.push(OsString::from(format!("-Zcodegen-backend={name}")))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ case $1 in
|
|||
git pull origin master
|
||||
branch=sync_cg_clif-$(date +%Y-%m-%d)
|
||||
git checkout -b "$branch"
|
||||
"$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git master
|
||||
"$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git main
|
||||
git push -u my "$branch"
|
||||
|
||||
# immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing
|
||||
|
|
|
|||
|
|
@ -50,23 +50,24 @@ EOF
|
|||
|
||||
cat <<EOF | git apply -
|
||||
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
|
||||
index cf4ef4ee310..fe78560fcaf 100644
|
||||
index a656927b1f6..44fc5546fac 100644
|
||||
--- a/src/bootstrap/src/core/config/config.rs
|
||||
+++ b/src/bootstrap/src/core/config/config.rs
|
||||
@@ -3138,13 +3138,6 @@ fn parse_download_ci_llvm(
|
||||
);
|
||||
}
|
||||
|
||||
- if b && self.is_running_on_ci {
|
||||
- // On CI, we must always rebuild LLVM if there were any modifications to it
|
||||
- panic!(
|
||||
- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
|
||||
- );
|
||||
- }
|
||||
-
|
||||
// If download-ci-llvm=true we also want to check that CI llvm is available
|
||||
b && llvm::is_ci_llvm_available_for_target(self, asserts)
|
||||
@@ -2249,14 +2249,6 @@ pub fn parse_download_ci_llvm<'a>(
|
||||
);
|
||||
}
|
||||
|
||||
- #[cfg(not(test))]
|
||||
- if b && dwn_ctx.is_running_on_ci && CiEnv::is_rust_lang_managed_ci_job() {
|
||||
- // On rust-lang CI, we must always rebuild LLVM if there were any modifications to it
|
||||
- panic!(
|
||||
- "\`llvm.download-ci-llvm\` cannot be set to \`true\` on CI. Use \`if-unchanged\` instead."
|
||||
- );
|
||||
- }
|
||||
-
|
||||
// If download-ci-llvm=true we also want to check that CI llvm is available
|
||||
b && llvm::is_ci_llvm_available_for_target(&dwn_ctx.host_target, asserts)
|
||||
}
|
||||
EOF
|
||||
|
||||
popd
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pushd rust
|
|||
|
||||
command -v rg >/dev/null 2>&1 || cargo install ripgrep
|
||||
|
||||
rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true
|
||||
rm -r tests/ui/{lto/,linkage*} || true
|
||||
for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do
|
||||
rm $test
|
||||
done
|
||||
|
|
@ -34,6 +34,7 @@ git checkout -- tests/ui/entry-point/auxiliary/bad_main_functions.rs
|
|||
# vendor intrinsics
|
||||
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
|
||||
rm tests/ui/simd/dont-invalid-bitcast-x86_64.rs # unimplemented llvm.x86.sse41.round.ps
|
||||
rm tests/ui/simd/intrinsic/generic-arithmetic-pass.rs # unimplemented simd_funnel_{shl,shr}
|
||||
|
||||
# exotic linkages
|
||||
rm tests/incremental/hashes/function_interfaces.rs
|
||||
|
|
@ -42,8 +43,14 @@ rm -r tests/run-make/naked-symbol-visibility
|
|||
|
||||
# variadic arguments
|
||||
rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
|
||||
rm tests/ui/c-variadic/naked.rs # same
|
||||
rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support
|
||||
rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support
|
||||
rm tests/ui/c-variadic/valid.rs # same
|
||||
rm tests/ui/c-variadic/trait-method.rs # same
|
||||
rm tests/ui/c-variadic/inherent-method.rs # same
|
||||
rm tests/ui/sanitizer/kcfi-c-variadic.rs # same
|
||||
rm tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs # variadics for calling conventions other than C unsupported
|
||||
rm tests/ui/delegation/fn-header.rs
|
||||
|
||||
# misc unimplemented things
|
||||
|
|
@ -56,8 +63,13 @@ rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't
|
|||
rm tests/ui/asm/global-asm-mono-sym-fn.rs # same
|
||||
rm tests/ui/asm/naked-asm-mono-sym-fn.rs # same
|
||||
rm tests/ui/asm/x86_64/goto.rs # inline asm labels not supported
|
||||
rm tests/ui/asm/label-operand.rs # same
|
||||
rm tests/ui/simd/simd-bitmask-notpow2.rs # non-pow-of-2 simd vector sizes
|
||||
rm -r tests/run-make/embed-source-dwarf # embedding sources in debuginfo
|
||||
rm -r tests/run-make/used-proc-macro # used(linker) isn't supported yet
|
||||
rm tests/ui/linking/no-gc-encapsulation-symbols.rs # same
|
||||
rm tests/ui/attributes/fn-align-dyn.rs # per-function alignment not supported
|
||||
rm -r tests/ui/explicit-tail-calls # tail calls
|
||||
rm -r tests/run-make/pointer-auth-link-with-c # pointer auth
|
||||
|
||||
# requires LTO
|
||||
rm -r tests/run-make/cdylib
|
||||
|
|
@ -69,15 +81,13 @@ rm -r tests/run-make/reachable-extern-fn-available-lto
|
|||
|
||||
# coverage instrumentation
|
||||
rm tests/ui/consts/precise-drop-with-coverage.rs
|
||||
rm tests/ui/issues/issue-85461.rs
|
||||
rm -r tests/ui/instrument-coverage/
|
||||
|
||||
# optimization tests
|
||||
# ==================
|
||||
rm tests/ui/codegen/issue-28950.rs # depends on stack size optimizations
|
||||
rm tests/ui/codegen/init-large-type.rs # same
|
||||
rm -r tests/run-make/fmt-write-bloat/ # tests an optimization
|
||||
rm tests/ui/statics/const_generics.rs # same
|
||||
rm tests/ui/statics/const_generics.rs # tests an optimization
|
||||
rm tests/ui/linking/executable-no-mangle-strip.rs # requires --gc-sections to work for statics
|
||||
|
||||
# backend specific tests
|
||||
|
|
@ -92,7 +102,7 @@ rm -r tests/run-make/llvm-location-discriminator-limit-dummy-span # same
|
|||
rm tests/ui/abi/stack-protector.rs # requires stack protector support
|
||||
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
|
||||
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
|
||||
rm -r tests/ui/optimization-remark.rs # same
|
||||
rm -r tests/ui/codegen/remark-flag-functionality.rs # same
|
||||
rm -r tests/run-make/print-to-output # requires --print relocation-models
|
||||
|
||||
# requires asm, llvm-ir and/or llvm-bc emit support
|
||||
|
|
@ -123,6 +133,8 @@ rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
|
|||
rm -r tests/run-make/strip # same
|
||||
rm -r tests/run-make-cargo/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source
|
||||
rm -r tests/run-make/translation # same
|
||||
rm -r tests/run-make-cargo/panic-immediate-abort-works # same
|
||||
rm -r tests/run-make-cargo/panic-immediate-abort-codegen # same
|
||||
rm -r tests/run-make/missing-unstable-trait-bound # This disables support for unstable features, but running cg_clif needs some unstable features
|
||||
rm -r tests/run-make/const-trait-stable-toolchain # same
|
||||
rm -r tests/run-make/print-request-help-stable-unstable # same
|
||||
|
|
@ -130,6 +142,7 @@ rm -r tests/run-make/incr-add-rust-src-component
|
|||
rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path
|
||||
rm -r tests/run-make/export/extern-opt # something about rustc version mismatches
|
||||
rm -r tests/run-make/export # same
|
||||
rm -r tests/ui/compiletest-self-test/compile-flags-incremental.rs # needs compiletest compiled with panic=unwind
|
||||
|
||||
# genuine bugs
|
||||
# ============
|
||||
|
|
@ -143,9 +156,9 @@ rm tests/ui/backtrace/synchronized-panic-handler.rs # missing needs-unwind annot
|
|||
rm tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs # same
|
||||
rm tests/ui/async-await/async-drop/async-drop-initial.rs # same (rust-lang/rust#140493)
|
||||
rm -r tests/ui/codegen/equal-pointers-unequal # make incorrect assumptions about the location of stack variables
|
||||
rm -r tests/run-make-cargo/rustdoc-scrape-examples-paths # FIXME(rust-lang/rust#145580) incr comp bug
|
||||
|
||||
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
|
||||
rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same
|
||||
rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # really slow with unoptimized libstd
|
||||
rm tests/ui/process/process-panic-after-fork.rs # same
|
||||
|
||||
cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ mod returning;
|
|||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
||||
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
|
||||
use cranelift_codegen::ir::{
|
||||
ArgumentPurpose, BlockArg, ExceptionTableData, ExceptionTableItem, ExceptionTag, SigRef,
|
||||
};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_abi::{CanonAbi, ExternAbi, X86Call};
|
||||
|
|
@ -20,10 +22,13 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::callconv::{FnAbi, PassMode};
|
||||
use smallvec::SmallVec;
|
||||
use rustc_target::spec::Arch;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use self::pass_mode::*;
|
||||
pub(crate) use self::returning::codegen_return;
|
||||
use crate::base::codegen_unwind_terminate;
|
||||
use crate::debuginfo::EXCEPTION_HANDLER_CLEANUP;
|
||||
use crate::prelude::*;
|
||||
|
||||
fn clif_sig_from_fn_abi<'tcx>(
|
||||
|
|
@ -81,7 +86,7 @@ pub(crate) fn get_function_sig<'tcx>(
|
|||
clif_sig_from_fn_abi(
|
||||
tcx,
|
||||
default_call_conv,
|
||||
&FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
|
||||
FullyMonomorphizedLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +115,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
/// Instance must be monomorphized
|
||||
pub(crate) fn get_function_ref(&mut self, inst: Instance<'tcx>) -> FuncRef {
|
||||
let func_id = import_function(self.tcx, self.module, inst);
|
||||
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
|
||||
let func_ref = self.module.declare_func_in_func(func_id, self.bcx.func);
|
||||
|
||||
if self.clif_comments.enabled() {
|
||||
self.add_comment(func_ref, format!("{:?}", inst));
|
||||
|
|
@ -155,7 +160,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
let ret = self.lib_call_unadjusted(name, params, returns, &args)[0];
|
||||
|
||||
Cow::Owned(vec![codegen_bitcast(self, types::I128, ret)])
|
||||
} else if ret_single_i128 && self.tcx.sess.target.arch == "s390x" {
|
||||
} else if ret_single_i128 && self.tcx.sess.target.arch == Arch::S390x {
|
||||
// Return i128 using a return area pointer on s390x.
|
||||
let mut params = params;
|
||||
let mut args = args.to_vec();
|
||||
|
|
@ -181,7 +186,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
) -> &[Value] {
|
||||
let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
|
||||
let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
|
||||
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
|
||||
let func_ref = self.module.declare_func_in_func(func_id, self.bcx.func);
|
||||
let call_inst = self.bcx.ins().call(func_ref, args);
|
||||
if self.clif_comments.enabled() {
|
||||
self.add_comment(func_ref, format!("{:?}", name));
|
||||
|
|
@ -266,7 +271,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
|
|||
// individual function arguments.
|
||||
|
||||
let tupled_arg_tys = match arg_ty.kind() {
|
||||
ty::Tuple(ref tys) => tys,
|
||||
ty::Tuple(tys) => tys,
|
||||
_ => bug!("spread argument isn't a tuple?! but {:?}", arg_ty),
|
||||
};
|
||||
|
||||
|
|
@ -296,7 +301,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
|
|||
Some(cvalue_for_param(fx, None, None, arg_abi, &mut block_params_iter).unwrap());
|
||||
}
|
||||
|
||||
assert!(arg_abis_iter.next().is_none(), "ArgAbi left behind");
|
||||
assert_eq!(arg_abis_iter.next(), None, "ArgAbi left behind for {:?}", fx.fn_abi);
|
||||
assert!(block_params_iter.next().is_none(), "arg_value left behind");
|
||||
|
||||
self::comments::add_locals_header_comment(fx);
|
||||
|
|
@ -380,7 +385,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
args: &[Spanned<Operand<'tcx>>],
|
||||
destination: Place<'tcx>,
|
||||
target: Option<BasicBlock>,
|
||||
_unwind: UnwindAction,
|
||||
unwind: UnwindAction,
|
||||
) {
|
||||
let func = codegen_operand(fx, func);
|
||||
let fn_sig = func.layout().ty.fn_sig(fx.tcx);
|
||||
|
|
@ -415,7 +420,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
if fx.tcx.symbol_name(instance).name.starts_with("llvm.") {
|
||||
crate::intrinsics::codegen_llvm_intrinsic_call(
|
||||
fx,
|
||||
&fx.tcx.symbol_name(instance).name,
|
||||
fx.tcx.symbol_name(instance).name,
|
||||
args,
|
||||
ret_place,
|
||||
target,
|
||||
|
|
@ -489,7 +494,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
};
|
||||
|
||||
let tupled_arguments = match pack_arg.value.layout().ty.kind() {
|
||||
ty::Tuple(ref tupled_arguments) => tupled_arguments,
|
||||
ty::Tuple(tupled_arguments) => tupled_arguments,
|
||||
_ => bug!("argument to function with \"rust-call\" ABI is not a tuple"),
|
||||
};
|
||||
|
||||
|
|
@ -515,12 +520,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
let args = args;
|
||||
assert_eq!(fn_abi.args.len(), args.len());
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CallTarget {
|
||||
Direct(FuncRef),
|
||||
Indirect(SigRef, Value),
|
||||
}
|
||||
|
||||
let (func_ref, first_arg_override) = match instance {
|
||||
// Trait object call
|
||||
Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => {
|
||||
|
|
@ -536,7 +535,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
}
|
||||
|
||||
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0].value, idx);
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
|
||||
(CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
|
||||
|
|
@ -556,7 +555,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
}
|
||||
|
||||
let func = func.load_scalar(fx);
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
|
||||
(CallTarget::Indirect(sig, func), None)
|
||||
|
|
@ -566,7 +565,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
|
||||
let mut call_args = return_ptr
|
||||
.into_iter()
|
||||
.chain(first_arg_override.into_iter())
|
||||
.chain(first_arg_override)
|
||||
.chain(
|
||||
args.into_iter()
|
||||
.enumerate()
|
||||
|
|
@ -579,21 +578,15 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
|
||||
// FIXME: Find a cleaner way to support varargs.
|
||||
if fn_abi.c_variadic {
|
||||
adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args);
|
||||
adjust_call_for_c_variadic(fx, fn_abi, source_info, func_ref, &mut call_args);
|
||||
}
|
||||
|
||||
let call_inst = match func_ref {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
|
||||
CallTarget::Indirect(sig, func_ptr) => {
|
||||
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
|
||||
}
|
||||
};
|
||||
|
||||
if fx.clif_comments.enabled() {
|
||||
with_no_trimmed_paths!(fx.add_comment(call_inst, format!("abi: {:?}", fn_abi)));
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
with_no_trimmed_paths!(fx.add_post_comment(nop_inst, format!("abi: {:?}", fn_abi)));
|
||||
}
|
||||
|
||||
fx.bcx.func.dfg.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>()
|
||||
codegen_call_with_unwind_action(fx, source_info.span, func_ref, unwind, &call_args, None)
|
||||
});
|
||||
|
||||
if let Some(dest) = target {
|
||||
|
|
@ -641,7 +634,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
.flat_map(|arg_abi| arg_abi.get_abi_param(fx.tcx).into_iter()),
|
||||
);
|
||||
|
||||
if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == "aarch64" {
|
||||
if fx.tcx.sess.target.is_like_darwin && fx.tcx.sess.target.arch == Arch::AArch64 {
|
||||
// Add any padding arguments needed for Apple AArch64.
|
||||
// There's no need to pad the argument list unless variadic arguments are actually being
|
||||
// passed.
|
||||
|
|
@ -703,7 +696,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
source_info: mir::SourceInfo,
|
||||
drop_place: CPlace<'tcx>,
|
||||
target: BasicBlock,
|
||||
_unwind: UnwindAction,
|
||||
unwind: UnwindAction,
|
||||
) {
|
||||
let ty = drop_place.layout().ty;
|
||||
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty);
|
||||
|
|
@ -747,11 +740,16 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx)
|
||||
.fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
// FIXME implement cleanup on exceptions
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
codegen_call_with_unwind_action(
|
||||
fx,
|
||||
source_info.span,
|
||||
CallTarget::Indirect(sig, drop_fn),
|
||||
unwind,
|
||||
&[ptr],
|
||||
Some(ret_block),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));
|
||||
|
|
@ -770,15 +768,146 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
if drop_instance.def.requires_caller_location(fx.tcx) {
|
||||
// Pass the caller location for `#[track_caller]`.
|
||||
let caller_location = fx.get_caller_location(source_info);
|
||||
call_args.extend(
|
||||
adjust_arg_for_abi(fx, caller_location, &fn_abi.args[1], false).into_iter(),
|
||||
);
|
||||
call_args.extend(adjust_arg_for_abi(
|
||||
fx,
|
||||
caller_location,
|
||||
&fn_abi.args[1],
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
let func_ref = fx.get_function_ref(drop_instance);
|
||||
fx.bcx.ins().call(func_ref, &call_args);
|
||||
// FIXME implement cleanup on exceptions
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
codegen_call_with_unwind_action(
|
||||
fx,
|
||||
source_info.span,
|
||||
CallTarget::Direct(func_ref),
|
||||
unwind,
|
||||
&call_args,
|
||||
Some(ret_block),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) enum CallTarget {
|
||||
Direct(FuncRef),
|
||||
Indirect(SigRef, Value),
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_call_with_unwind_action(
|
||||
fx: &mut FunctionCx<'_, '_, '_>,
|
||||
span: Span,
|
||||
func_ref: CallTarget,
|
||||
mut unwind: UnwindAction,
|
||||
call_args: &[Value],
|
||||
target_block: Option<Block>,
|
||||
) -> SmallVec<[Value; 2]> {
|
||||
let sig_ref = match func_ref {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
|
||||
CallTarget::Indirect(sig_ref, _func_ptr) => sig_ref,
|
||||
};
|
||||
|
||||
if target_block.is_some() {
|
||||
assert!(fx.bcx.func.dfg.signatures[sig_ref].returns.is_empty());
|
||||
}
|
||||
|
||||
if cfg!(not(feature = "unwinding")) {
|
||||
unwind = UnwindAction::Unreachable;
|
||||
}
|
||||
|
||||
match unwind {
|
||||
UnwindAction::Continue | UnwindAction::Unreachable => {
|
||||
let call_inst = match func_ref {
|
||||
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, call_args),
|
||||
CallTarget::Indirect(sig, func_ptr) => {
|
||||
fx.bcx.ins().call_indirect(sig, func_ptr, call_args)
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(target_block) = target_block {
|
||||
fx.bcx.ins().jump(target_block, &[]);
|
||||
smallvec![]
|
||||
} else {
|
||||
fx.bcx
|
||||
.func
|
||||
.dfg
|
||||
.inst_results(call_inst)
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<SmallVec<[Value; 2]>>()
|
||||
}
|
||||
}
|
||||
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) => {
|
||||
let returns_types = fx.bcx.func.dfg.signatures[sig_ref]
|
||||
.returns
|
||||
.iter()
|
||||
.map(|return_param| return_param.value_type)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let fallthrough_block = fx.bcx.create_block();
|
||||
let fallthrough_block_call_args = returns_types
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| BlockArg::TryCallRet(i.try_into().unwrap()))
|
||||
.collect::<Vec<_>>();
|
||||
let fallthrough_block_call = fx.bcx.func.dfg.block_call(
|
||||
target_block.unwrap_or(fallthrough_block),
|
||||
&fallthrough_block_call_args,
|
||||
);
|
||||
let pre_cleanup_block = fx.bcx.create_block();
|
||||
let pre_cleanup_block_call =
|
||||
fx.bcx.func.dfg.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
|
||||
let exception_table = fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
|
||||
sig_ref,
|
||||
fallthrough_block_call,
|
||||
[ExceptionTableItem::Tag(
|
||||
ExceptionTag::with_number(EXCEPTION_HANDLER_CLEANUP).unwrap(),
|
||||
pre_cleanup_block_call,
|
||||
)],
|
||||
));
|
||||
|
||||
match func_ref {
|
||||
CallTarget::Direct(func_ref) => {
|
||||
fx.bcx.ins().try_call(func_ref, call_args, exception_table);
|
||||
}
|
||||
CallTarget::Indirect(_sig, func_ptr) => {
|
||||
fx.bcx.ins().try_call_indirect(func_ptr, call_args, exception_table);
|
||||
}
|
||||
}
|
||||
|
||||
fx.bcx.seal_block(pre_cleanup_block);
|
||||
fx.bcx.switch_to_block(pre_cleanup_block);
|
||||
fx.bcx.set_cold_block(pre_cleanup_block);
|
||||
match unwind {
|
||||
UnwindAction::Continue | UnwindAction::Unreachable => unreachable!(),
|
||||
UnwindAction::Cleanup(cleanup) => {
|
||||
let exception_ptr =
|
||||
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
|
||||
fx.bcx.def_var(fx.exception_slot, exception_ptr);
|
||||
let cleanup_block = fx.get_block(cleanup);
|
||||
fx.bcx.ins().jump(cleanup_block, &[]);
|
||||
}
|
||||
UnwindAction::Terminate(reason) => {
|
||||
// FIXME dedup terminate blocks
|
||||
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
|
||||
|
||||
codegen_unwind_terminate(fx, span, reason);
|
||||
}
|
||||
}
|
||||
|
||||
if target_block.is_none() {
|
||||
fx.bcx.seal_block(fallthrough_block);
|
||||
fx.bcx.switch_to_block(fallthrough_block);
|
||||
let returns = returns_types
|
||||
.into_iter()
|
||||
.map(|ty| fx.bcx.append_block_param(fallthrough_block, ty))
|
||||
.collect();
|
||||
fx.bcx.ins().nop();
|
||||
returns
|
||||
} else {
|
||||
smallvec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -787,25 +916,25 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
|
||||
let param = AbiParam::new(ty);
|
||||
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
|
||||
match (&*tcx.sess.target.arch, &*tcx.sess.target.vendor) {
|
||||
("x86_64", _) | ("aarch64", "apple") => match (ty, is_signed) {
|
||||
match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) {
|
||||
(Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) {
|
||||
(types::I8 | types::I16, true) => param.sext(),
|
||||
(types::I8 | types::I16, false) => param.uext(),
|
||||
_ => param,
|
||||
},
|
||||
("aarch64", _) => param,
|
||||
("riscv64", _) => match (ty, is_signed) {
|
||||
(Arch::AArch64, _) => param,
|
||||
(Arch::RiscV64, _) => match (ty, is_signed) {
|
||||
(types::I32, _) | (_, true) => param.sext(),
|
||||
_ => param.uext(),
|
||||
},
|
||||
("s390x", _) => {
|
||||
(Arch::S390x, _) => {
|
||||
if is_signed {
|
||||
param.sext()
|
||||
} else {
|
||||
param.uext()
|
||||
}
|
||||
}
|
||||
_ => unimplemented!("{:?}", tcx.sess.target.arch),
|
||||
(arch, _) => unimplemented!("{arch:?}"),
|
||||
}
|
||||
} else {
|
||||
param
|
||||
|
|
|
|||
|
|
@ -209,12 +209,7 @@ pub(super) fn to_casted_value<'tcx>(
|
|||
cast_target_to_abi_params(cast)
|
||||
.into_iter()
|
||||
.map(|(offset, param)| {
|
||||
let val = ptr.offset_i64(fx, offset.bytes() as i64).load(
|
||||
fx,
|
||||
param.value_type,
|
||||
MemFlags::new(),
|
||||
);
|
||||
val
|
||||
ptr.offset_i64(fx, offset.bytes() as i64).load(fx, param.value_type, MemFlags::new())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use rustc_middle::ty::TypeVisitableExt;
|
|||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_session::config::OutputFilenames;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
|
||||
|
|
@ -25,11 +27,13 @@ pub(crate) struct CodegenedFunction {
|
|||
func: Function,
|
||||
clif_comments: CommentWriter,
|
||||
func_debug_cx: Option<FunctionDebugContext>,
|
||||
inline_asm: String,
|
||||
}
|
||||
|
||||
pub(crate) fn codegen_fn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cx: &mut crate::CodegenCx,
|
||||
cgu_name: Symbol,
|
||||
mut debug_context: Option<&mut DebugContext>,
|
||||
type_dbg: &mut TypeDebugContext<'tcx>,
|
||||
cached_func: Function,
|
||||
module: &mut dyn Module,
|
||||
|
|
@ -60,7 +64,9 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
func.clear();
|
||||
func.name = UserFuncName::user(0, func_id.as_u32());
|
||||
func.signature = sig;
|
||||
func.collect_debug_info();
|
||||
if debug_context.is_some() {
|
||||
func.collect_debug_info();
|
||||
}
|
||||
|
||||
let mut bcx = FunctionBuilder::new(&mut func, &mut func_ctx);
|
||||
|
||||
|
|
@ -74,23 +80,27 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
// Make FunctionCx
|
||||
let target_config = module.target_config();
|
||||
let pointer_type = target_config.pointer_type();
|
||||
assert_eq!(pointer_ty(tcx), pointer_type);
|
||||
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance, fn_abi);
|
||||
|
||||
let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
|
||||
let func_debug_cx = if let Some(debug_context) = debug_context.as_deref_mut() {
|
||||
Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let exception_slot = bcx.declare_var(pointer_type);
|
||||
|
||||
let mut fx = FunctionCx {
|
||||
cx,
|
||||
module,
|
||||
debug_context,
|
||||
tcx,
|
||||
target_config,
|
||||
pointer_type,
|
||||
constants_cx: ConstantCx::new(),
|
||||
func_debug_cx,
|
||||
|
||||
cgu_name,
|
||||
instance,
|
||||
symbol_name,
|
||||
mir,
|
||||
|
|
@ -100,9 +110,11 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
block_map,
|
||||
local_map: IndexVec::with_capacity(mir.local_decls.len()),
|
||||
caller_location: None, // set by `codegen_fn_prelude`
|
||||
exception_slot,
|
||||
|
||||
clif_comments,
|
||||
next_ssa_var: 0,
|
||||
inline_asm: String::new(),
|
||||
inline_asm_index: 0,
|
||||
};
|
||||
|
||||
tcx.prof.generic_activity("codegen clif ir").run(|| codegen_fn_body(&mut fx, start_block));
|
||||
|
|
@ -113,10 +125,11 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
let symbol_name = fx.symbol_name;
|
||||
let clif_comments = fx.clif_comments;
|
||||
let func_debug_cx = fx.func_debug_cx;
|
||||
let inline_asm = fx.inline_asm;
|
||||
|
||||
fx.constants_cx.finalize(fx.tcx, &mut *fx.module);
|
||||
|
||||
if cx.should_write_ir {
|
||||
if crate::pretty_clif::should_write_ir(tcx.sess) {
|
||||
crate::pretty_clif::write_clif_file(
|
||||
tcx.output_filenames(()),
|
||||
&symbol_name,
|
||||
|
|
@ -130,20 +143,24 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
// Verify function
|
||||
verify_func(tcx, &clif_comments, &func);
|
||||
|
||||
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
|
||||
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx, inline_asm }
|
||||
}
|
||||
|
||||
pub(crate) fn compile_fn(
|
||||
cx: &mut crate::CodegenCx,
|
||||
profiler: &SelfProfilerRef,
|
||||
output_filenames: &OutputFilenames,
|
||||
should_write_ir: bool,
|
||||
cached_context: &mut Context,
|
||||
module: &mut dyn Module,
|
||||
debug_context: Option<&mut DebugContext>,
|
||||
global_asm: &mut String,
|
||||
codegened_func: CodegenedFunction,
|
||||
) {
|
||||
let _timer =
|
||||
profiler.generic_activity_with_arg("compile function", &*codegened_func.symbol_name);
|
||||
|
||||
let clif_comments = codegened_func.clif_comments;
|
||||
global_asm.push_str(&codegened_func.inline_asm);
|
||||
|
||||
// Store function in context
|
||||
let context = cached_context;
|
||||
|
|
@ -180,7 +197,7 @@ pub(crate) fn compile_fn(
|
|||
|
||||
// Define function
|
||||
profiler.generic_activity("define function").run(|| {
|
||||
context.want_disasm = cx.should_write_ir;
|
||||
context.want_disasm = should_write_ir;
|
||||
match module.define_function(codegened_func.func_id, context) {
|
||||
Ok(()) => {}
|
||||
Err(ModuleError::Compilation(CodegenError::ImplLimitExceeded)) => {
|
||||
|
|
@ -210,10 +227,10 @@ pub(crate) fn compile_fn(
|
|||
}
|
||||
});
|
||||
|
||||
if cx.should_write_ir {
|
||||
if should_write_ir {
|
||||
// Write optimized function to file for debugging
|
||||
crate::pretty_clif::write_clif_file(
|
||||
&cx.output_filenames,
|
||||
output_filenames,
|
||||
&codegened_func.symbol_name,
|
||||
"opt",
|
||||
module.isa(),
|
||||
|
|
@ -223,7 +240,7 @@ pub(crate) fn compile_fn(
|
|||
|
||||
if let Some(disasm) = &context.compiled_code().unwrap().vcode {
|
||||
crate::pretty_clif::write_ir_file(
|
||||
&cx.output_filenames,
|
||||
output_filenames,
|
||||
&format!("{}.vcode", codegened_func.symbol_name),
|
||||
|file| file.write_all(disasm.as_bytes()),
|
||||
)
|
||||
|
|
@ -231,7 +248,6 @@ pub(crate) fn compile_fn(
|
|||
}
|
||||
|
||||
// Define debuginfo for function
|
||||
let debug_context = &mut cx.debug_context;
|
||||
profiler.generic_activity("generate debug info").run(|| {
|
||||
if let Some(debug_context) = debug_context {
|
||||
codegened_func.func_debug_cx.unwrap().finalize(
|
||||
|
|
@ -250,12 +266,12 @@ fn verify_func(tcx: TyCtxt<'_>, writer: &crate::pretty_clif::CommentWriter, func
|
|||
|
||||
tcx.prof.generic_activity("verify clif ir").run(|| {
|
||||
let flags = cranelift_codegen::settings::Flags::new(cranelift_codegen::settings::builder());
|
||||
match cranelift_codegen::verify_function(&func, &flags) {
|
||||
match cranelift_codegen::verify_function(func, &flags) {
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
tcx.dcx().err(format!("{:?}", err));
|
||||
let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error(
|
||||
&func,
|
||||
func,
|
||||
Some(Box::new(writer)),
|
||||
err,
|
||||
);
|
||||
|
|
@ -295,11 +311,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|||
}
|
||||
|
||||
if bb_data.is_cleanup {
|
||||
// Unwinding after panicking is not supported
|
||||
continue;
|
||||
if cfg!(not(feature = "unwinding")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME Once unwinding is supported and Cranelift supports marking blocks as cold, do
|
||||
// so for cleanup blocks.
|
||||
fx.bcx.set_cold_block(block);
|
||||
}
|
||||
|
||||
fx.bcx.ins().nop();
|
||||
|
|
@ -369,7 +385,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|||
fx.bcx.ins().nop();
|
||||
|
||||
match &**msg {
|
||||
AssertKind::BoundsCheck { ref len, ref index } => {
|
||||
AssertKind::BoundsCheck { len, index } => {
|
||||
let len = codegen_operand(fx, len).load_scalar(fx);
|
||||
let index = codegen_operand(fx, index).load_scalar(fx);
|
||||
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
||||
|
|
@ -382,7 +398,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|||
source_info.span,
|
||||
);
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
|
||||
AssertKind::MisalignedPointerDereference { required, found } => {
|
||||
let required = codegen_operand(fx, required).load_scalar(fx);
|
||||
let found = codegen_operand(fx, found).load_scalar(fx);
|
||||
let location = fx.get_caller_location(source_info).load_scalar(fx);
|
||||
|
|
@ -538,14 +554,22 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
|
|||
template,
|
||||
operands,
|
||||
*options,
|
||||
targets.get(0).copied(),
|
||||
targets.first().copied(),
|
||||
);
|
||||
}
|
||||
TerminatorKind::UnwindTerminate(reason) => {
|
||||
codegen_unwind_terminate(fx, source_info.span, *reason);
|
||||
}
|
||||
TerminatorKind::UnwindResume => {
|
||||
// FIXME implement unwinding
|
||||
if cfg!(feature = "unwinding") {
|
||||
let exception_ptr = fx.bcx.use_var(fx.exception_slot);
|
||||
fx.lib_call(
|
||||
"_Unwind_Resume",
|
||||
vec![AbiParam::new(fx.pointer_type)],
|
||||
vec![],
|
||||
&[exception_ptr],
|
||||
);
|
||||
}
|
||||
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
||||
}
|
||||
TerminatorKind::Unreachable => {
|
||||
|
|
@ -841,17 +865,8 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
|
|||
fields.iter(),
|
||||
)
|
||||
.bytes(),
|
||||
NullOp::UbChecks => {
|
||||
let val = fx.tcx.sess.ub_checks();
|
||||
let val = CValue::by_val(
|
||||
fx.bcx.ins().iconst(types::I8, i64::from(val)),
|
||||
fx.layout_of(fx.tcx.types.bool),
|
||||
);
|
||||
lval.write_cvalue(fx, val);
|
||||
return;
|
||||
}
|
||||
NullOp::ContractChecks => {
|
||||
let val = fx.tcx.sess.contract_checks();
|
||||
NullOp::RuntimeChecks(kind) => {
|
||||
let val = kind.value(fx.tcx.sess);
|
||||
let val = CValue::by_val(
|
||||
fx.bcx.ins().iconst(types::I8, i64::from(val)),
|
||||
fx.layout_of(fx.tcx.types.bool),
|
||||
|
|
@ -929,7 +944,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
|
|||
| StatementKind::AscribeUserType(..) => {}
|
||||
|
||||
StatementKind::Coverage { .. } => unreachable!(),
|
||||
StatementKind::Intrinsic(ref intrinsic) => match &**intrinsic {
|
||||
StatementKind::Intrinsic(intrinsic) => match &**intrinsic {
|
||||
// We ignore `assume` intrinsics, they are only useful for optimizations
|
||||
NonDivergingIntrinsic::Assume(_) => {}
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
|
||||
|
|
@ -1060,7 +1075,7 @@ pub(crate) fn codegen_panic_nounwind<'tcx>(
|
|||
msg_str: &str,
|
||||
span: Span,
|
||||
) {
|
||||
let msg_ptr = fx.anonymous_str(msg_str);
|
||||
let msg_ptr = crate::constant::pointer_for_anonymous_str(fx, msg_str);
|
||||
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
|
||||
let args = [msg_ptr, msg_len];
|
||||
|
||||
|
|
@ -1085,7 +1100,7 @@ fn codegen_panic_inner<'tcx>(
|
|||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
lang_item: rustc_hir::LangItem,
|
||||
args: &[Value],
|
||||
_unwind: UnwindAction,
|
||||
unwind: UnwindAction,
|
||||
span: Span,
|
||||
) {
|
||||
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
|
||||
|
|
@ -1101,14 +1116,23 @@ fn codegen_panic_inner<'tcx>(
|
|||
|
||||
let symbol_name = fx.tcx.symbol_name(instance).name;
|
||||
|
||||
// FIXME implement cleanup on exceptions
|
||||
let sig = Signature {
|
||||
params: args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
|
||||
returns: vec![],
|
||||
call_conv: fx.target_config.default_call_conv,
|
||||
};
|
||||
let func_id = fx.module.declare_function(symbol_name, Linkage::Import, &sig).unwrap();
|
||||
let func_ref = fx.module.declare_func_in_func(func_id, fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(func_ref, format!("{:?}", symbol_name));
|
||||
}
|
||||
|
||||
fx.lib_call(
|
||||
symbol_name,
|
||||
args.iter().map(|&arg| AbiParam::new(fx.bcx.func.dfg.value_type(arg))).collect(),
|
||||
vec![],
|
||||
args,
|
||||
);
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(nop_inst, format!("panic {}", symbol_name));
|
||||
}
|
||||
|
||||
codegen_call_with_unwind_action(fx, span, CallTarget::Direct(func_ref), unwind, args, None);
|
||||
|
||||
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
use rustc_target::spec::Arch;
|
||||
|
||||
use crate::compiler_builtins::CMP_RESULT_TY;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub(crate) fn f16_to_f32(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
|
||||
let (value, arg_ty) =
|
||||
if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" {
|
||||
if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64 {
|
||||
(
|
||||
fx.bcx.ins().bitcast(types::I16, MemFlags::new(), value),
|
||||
lib_call_arg_param(fx.tcx, types::I16, false),
|
||||
|
|
@ -19,7 +22,8 @@ fn f16_to_f64(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
|
|||
}
|
||||
|
||||
pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
|
||||
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" {
|
||||
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
|
||||
{
|
||||
types::I16
|
||||
} else {
|
||||
types::F16
|
||||
|
|
@ -34,7 +38,8 @@ pub(crate) fn f32_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value
|
|||
}
|
||||
|
||||
fn f64_to_f16(fx: &mut FunctionCx<'_, '_, '_>, value: Value) -> Value {
|
||||
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == "x86_64" {
|
||||
let ret_ty = if fx.tcx.sess.target.vendor == "apple" && fx.tcx.sess.target.arch == Arch::X86_64
|
||||
{
|
||||
types::I16
|
||||
} else {
|
||||
types::F16
|
||||
|
|
@ -70,15 +75,11 @@ pub(crate) fn fcmp(fx: &mut FunctionCx<'_, '_, '_>, cc: FloatCC, lhs: Value, rhs
|
|||
let res = fx.lib_call(
|
||||
name,
|
||||
vec![AbiParam::new(types::F128), AbiParam::new(types::F128)],
|
||||
// FIXME(rust-lang/compiler-builtins#919): This should be `I64` on non-AArch64
|
||||
// architectures, but switching it before compiler-builtins is fixed causes test
|
||||
// failures.
|
||||
vec![AbiParam::new(types::I32)],
|
||||
vec![AbiParam::new(CMP_RESULT_TY)],
|
||||
&[lhs, rhs],
|
||||
)[0];
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let res = fx.bcx.ins().icmp(int_cc, res, zero);
|
||||
res
|
||||
let zero = fx.bcx.ins().iconst(CMP_RESULT_TY, 0);
|
||||
fx.bcx.ins().icmp(int_cc, res, zero)
|
||||
}
|
||||
_ => unreachable!("{ty:?}"),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
|
||||
use rustc_abi::{Float, Integer, Primitive};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_middle::ty::layout::{
|
||||
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
|
||||
};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
use rustc_target::spec::{Arch, HasTargetSpec, Target};
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
use crate::debuginfo::FunctionDebugContext;
|
||||
|
|
@ -256,7 +257,7 @@ pub(crate) fn create_wrapper_function(
|
|||
.map(|param| func.dfg.append_block_param(block, param.value_type))
|
||||
.collect::<Vec<Value>>();
|
||||
|
||||
let callee_func_ref = module.declare_func_in_func(callee_func_id, &mut bcx.func);
|
||||
let callee_func_ref = module.declare_func_in_func(callee_func_id, bcx.func);
|
||||
let call_inst = bcx.ins().call(callee_func_ref, &args);
|
||||
let results = bcx.inst_results(call_inst).to_vec(); // Clone to prevent borrow error
|
||||
|
||||
|
|
@ -268,14 +269,15 @@ pub(crate) fn create_wrapper_function(
|
|||
}
|
||||
|
||||
pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
||||
pub(crate) cx: &'clif mut crate::CodegenCx,
|
||||
pub(crate) module: &'m mut dyn Module,
|
||||
pub(crate) debug_context: Option<&'clif mut DebugContext>,
|
||||
pub(crate) tcx: TyCtxt<'tcx>,
|
||||
pub(crate) target_config: TargetFrontendConfig, // Cached from module
|
||||
pub(crate) pointer_type: Type, // Cached from module
|
||||
pub(crate) constants_cx: ConstantCx,
|
||||
pub(crate) func_debug_cx: Option<FunctionDebugContext>,
|
||||
|
||||
pub(crate) cgu_name: Symbol,
|
||||
pub(crate) instance: Instance<'tcx>,
|
||||
pub(crate) symbol_name: String,
|
||||
pub(crate) mir: &'tcx Body<'tcx>,
|
||||
|
|
@ -288,10 +290,13 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
|||
/// When `#[track_caller]` is used, the implicit caller location is stored in this variable.
|
||||
pub(crate) caller_location: Option<CValue<'tcx>>,
|
||||
|
||||
/// During cleanup the exception pointer will be stored in this variable.
|
||||
pub(crate) exception_slot: Variable,
|
||||
|
||||
pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
|
||||
|
||||
/// This should only be accessed by `CPlace::new_var`.
|
||||
pub(crate) next_ssa_var: u32,
|
||||
pub(crate) inline_asm: String,
|
||||
pub(crate) inline_asm_index: u32,
|
||||
}
|
||||
|
||||
impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
|
||||
|
|
@ -369,17 +374,17 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
|
||||
pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer {
|
||||
assert!(
|
||||
size % align == 0,
|
||||
size.is_multiple_of(align),
|
||||
"size must be a multiple of alignment (size={size}, align={align})"
|
||||
);
|
||||
|
||||
let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 };
|
||||
let abi_align = if self.tcx.sess.target.arch == Arch::S390x { 8 } else { 16 };
|
||||
if align <= abi_align {
|
||||
let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
|
||||
kind: StackSlotKind::ExplicitSlot,
|
||||
// FIXME Don't force the size to a multiple of <abi_align> bytes once Cranelift gets
|
||||
// a way to specify stack slot alignment.
|
||||
size: (size + abi_align - 1) / abi_align * abi_align,
|
||||
size: size.div_ceil(abi_align) * abi_align,
|
||||
align_shift: 4,
|
||||
});
|
||||
Pointer::stack_slot(stack_slot)
|
||||
|
|
@ -401,7 +406,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
}
|
||||
|
||||
pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
|
||||
if let Some(debug_context) = &mut self.cx.debug_context {
|
||||
if let Some(debug_context) = &mut self.debug_context {
|
||||
let (file_id, line, column) =
|
||||
debug_context.get_span_loc(self.tcx, self.mir.span, source_info.span);
|
||||
|
||||
|
|
@ -417,21 +422,6 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
|
||||
let mut data = DataDescription::new();
|
||||
data.define(msg.as_bytes().to_vec().into_boxed_slice());
|
||||
let msg_id = self.module.declare_anonymous_data(false, false).unwrap();
|
||||
|
||||
// Ignore DuplicateDefinition error, as the data will be the same
|
||||
let _ = self.module.define_data(msg_id, &data);
|
||||
|
||||
let local_msg_id = self.module.declare_data_in_func(msg_id, self.bcx.func);
|
||||
if self.clif_comments.enabled() {
|
||||
self.add_comment(local_msg_id, msg);
|
||||
}
|
||||
self.bcx.ins().global_value(self.pointer_type, local_msg_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct FullyMonomorphizedLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
|
||||
|
|
|
|||
|
|
@ -3,11 +3,34 @@ use std::ffi::c_int;
|
|||
#[cfg(feature = "jit")]
|
||||
use std::ffi::c_void;
|
||||
|
||||
use cranelift_codegen::ir::{Type, types};
|
||||
|
||||
// FIXME replace with core::ffi::c_size_t once stabilized
|
||||
#[allow(non_camel_case_types)]
|
||||
#[cfg(feature = "jit")]
|
||||
type size_t = usize;
|
||||
|
||||
// Needs to stay in sync with compiler-builtins
|
||||
|
||||
// Aarch64 uses `int` rather than a pointer-sized value.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
|
||||
#[cfg(feature = "jit")]
|
||||
type CmpResult = i32;
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
|
||||
pub(crate) const CMP_RESULT_TY: Type = types::I32;
|
||||
|
||||
// In compiler-rt, LLP64 ABIs use `long long` and everything else uses `long`. In effect,
|
||||
// this means the return value is always pointer-sized.
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
|
||||
#[cfg(feature = "jit")]
|
||||
type CmpResult = isize;
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub(crate) const CMP_RESULT_TY: Type = types::I32;
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm64ec")))]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub(crate) const CMP_RESULT_TY: Type = types::I64;
|
||||
|
||||
macro_rules! builtin_functions {
|
||||
(
|
||||
$register:ident;
|
||||
|
|
@ -18,7 +41,7 @@ macro_rules! builtin_functions {
|
|||
) => {
|
||||
#[cfg(feature = "jit")]
|
||||
#[allow(improper_ctypes)]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
$(
|
||||
$(#[$attr])?
|
||||
fn $name($($arg_name: $arg_ty),*) -> $ret_ty;
|
||||
|
|
@ -85,15 +108,18 @@ builtin_functions! {
|
|||
fn __divtf3(a: f128, b: f128) -> f128;
|
||||
fn fmodf(a: f32, b: f32) -> f32;
|
||||
fn fmod(a: f64, b: f64) -> f64;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn fmodf128(a: f128, b: f128) -> f128;
|
||||
// float comparison
|
||||
fn __eqtf2(a: f128, b: f128) -> i32;
|
||||
fn __netf2(a: f128, b: f128) -> i32;
|
||||
fn __lttf2(a: f128, b: f128) -> i32;
|
||||
fn __letf2(a: f128, b: f128) -> i32;
|
||||
fn __gttf2(a: f128, b: f128) -> i32;
|
||||
fn __getf2(a: f128, b: f128) -> i32;
|
||||
fn __eqtf2(a: f128, b: f128) -> CmpResult;
|
||||
fn __netf2(a: f128, b: f128) -> CmpResult;
|
||||
fn __lttf2(a: f128, b: f128) -> CmpResult;
|
||||
fn __letf2(a: f128, b: f128) -> CmpResult;
|
||||
fn __gttf2(a: f128, b: f128) -> CmpResult;
|
||||
fn __getf2(a: f128, b: f128) -> CmpResult;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn fminimumf128(a: f128, b: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn fmaximumf128(a: f128, b: f128) -> f128;
|
||||
// Cranelift float libcalls
|
||||
fn fmaf(a: f32, b: f32, c: f32) -> f32;
|
||||
|
|
@ -127,16 +153,27 @@ builtin_functions! {
|
|||
fn sin(f: f64) -> f64;
|
||||
fn cosf(f: f32) -> f32;
|
||||
fn cos(f: f64) -> f64;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn fmaf128(a: f128, b: f128, c: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn floorf16(f: f16) -> f16;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn floorf128(f: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn ceilf16(f: f16) -> f16;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn ceilf128(f: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn truncf16(f: f16) -> f16;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn truncf128(f: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn rintf16(f: f16) -> f16;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn rintf128(f: f128) -> f128;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn sqrtf16(f: f16) -> f16;
|
||||
#[cfg(not(all(target_os = "windows", target_env = "gnu")))]
|
||||
fn sqrtf128(f: f128) -> f128;
|
||||
// FIXME(f16_f128): Add other float intrinsics as compiler-builtins gains support (meaning they
|
||||
// are available on all targets).
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/// Configuration of cg_clif as passed in through `-Cllvm-args` and various env vars.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct BackendConfig {
|
||||
/// Should the crate be AOT compiled or JIT executed.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use cranelift_module::*;
|
||||
use rustc_const_eval::interpret::CTFE_ALLOC_SALT;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::interpret::{
|
||||
|
|
@ -64,7 +65,7 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
|||
// For a declaration the stated mutability doesn't matter.
|
||||
false,
|
||||
);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
|
||||
}
|
||||
|
|
@ -110,7 +111,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
ConstValue::Scalar(x) => match x {
|
||||
Scalar::Int(int) => {
|
||||
if fx.clif_type(layout.ty).is_some() {
|
||||
return CValue::const_val(fx, layout, int);
|
||||
CValue::const_val(fx, layout, int)
|
||||
} else {
|
||||
let raw_val = int.size().truncate(int.to_bits(int.size()));
|
||||
let val = match int.size().bytes() {
|
||||
|
|
@ -140,11 +141,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
let base_addr = match fx.tcx.global_alloc(alloc_id) {
|
||||
GlobalAlloc::Memory(alloc) => {
|
||||
if alloc.inner().len() == 0 {
|
||||
let val = alloc.inner().align.bytes().wrapping_add(offset.bytes());
|
||||
fx.bcx.ins().iconst(
|
||||
fx.pointer_type,
|
||||
fx.tcx.truncate_to_target_usize(val) as i64,
|
||||
)
|
||||
fx.bcx.ins().iconst(fx.pointer_type, alloc.inner().align.bytes() as i64)
|
||||
} else {
|
||||
let data_id = data_id_for_alloc_id(
|
||||
&mut fx.constants_cx,
|
||||
|
|
@ -153,17 +150,16 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
alloc.inner().mutability,
|
||||
);
|
||||
let local_data_id =
|
||||
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
fx.module.declare_data_in_func(data_id, fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
|
||||
}
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
}
|
||||
GlobalAlloc::Function { instance, .. } => {
|
||||
let func_id = crate::abi::import_function(fx.tcx, fx.module, instance);
|
||||
let local_func_id =
|
||||
fx.module.declare_func_in_func(func_id, &mut fx.bcx.func);
|
||||
let local_func_id = fx.module.declare_func_in_func(func_id, fx.bcx.func);
|
||||
fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
|
||||
}
|
||||
GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
|
|
@ -176,9 +172,8 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
fx.tcx.instantiate_bound_regions_with_erased(principal)
|
||||
}),
|
||||
);
|
||||
let local_data_id =
|
||||
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
|
||||
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
GlobalAlloc::TypeId { .. } => {
|
||||
return CValue::const_val(
|
||||
|
|
@ -194,16 +189,26 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
// For a declaration the stated mutability doesn't matter.
|
||||
false,
|
||||
);
|
||||
let local_data_id =
|
||||
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_id));
|
||||
}
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
if fx
|
||||
.tcx
|
||||
.codegen_fn_attrs(def_id)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::THREAD_LOCAL)
|
||||
{
|
||||
fx.bcx.ins().tls_value(fx.pointer_type, local_data_id)
|
||||
} else {
|
||||
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
}
|
||||
};
|
||||
let val = if offset.bytes() != 0 {
|
||||
fx.bcx.ins().iadd_imm(base_addr, i64::try_from(offset.bytes()).unwrap())
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iadd_imm(base_addr, fx.tcx.truncate_to_target_usize(offset.bytes()) as i64)
|
||||
} else {
|
||||
base_addr
|
||||
};
|
||||
|
|
@ -211,32 +216,28 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||
}
|
||||
},
|
||||
ConstValue::Indirect { alloc_id, offset } => CValue::by_ref(
|
||||
pointer_for_allocation(fx, alloc_id)
|
||||
Pointer::new(pointer_for_allocation(fx, alloc_id))
|
||||
.offset_i64(fx, i64::try_from(offset.bytes()).unwrap()),
|
||||
layout,
|
||||
),
|
||||
ConstValue::Slice { alloc_id, meta } => {
|
||||
let ptr = pointer_for_allocation(fx, alloc_id).get_addr(fx);
|
||||
let ptr = pointer_for_allocation(fx, alloc_id);
|
||||
let len = fx.bcx.ins().iconst(fx.pointer_type, meta as i64);
|
||||
CValue::by_val_pair(ptr, len, layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pointer_for_allocation<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
alloc_id: AllocId,
|
||||
) -> crate::pointer::Pointer {
|
||||
fn pointer_for_allocation<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, alloc_id: AllocId) -> Value {
|
||||
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
let data_id =
|
||||
data_id_for_alloc_id(&mut fx.constants_cx, fx.module, alloc_id, alloc.inner().mutability);
|
||||
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
|
||||
}
|
||||
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
|
||||
crate::pointer::Pointer::new(global_ptr)
|
||||
fx.bcx.ins().symbol_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
|
||||
fn data_id_for_alloc_id(
|
||||
|
|
@ -262,6 +263,11 @@ pub(crate) fn data_id_for_vtable<'tcx>(
|
|||
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
|
||||
}
|
||||
|
||||
pub(crate) fn pointer_for_anonymous_str(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) -> Value {
|
||||
let alloc_id = fx.tcx.allocate_bytes_dedup(msg.as_bytes(), CTFE_ALLOC_SALT);
|
||||
pointer_for_allocation(fx, alloc_id)
|
||||
}
|
||||
|
||||
fn data_id_for_static(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut dyn Module,
|
||||
|
|
@ -345,7 +351,7 @@ fn data_id_for_static(
|
|||
Linkage::Import
|
||||
};
|
||||
|
||||
let data_id = match module.declare_data(
|
||||
match module.declare_data(
|
||||
symbol_name,
|
||||
linkage,
|
||||
definition_writable,
|
||||
|
|
@ -356,9 +362,7 @@ fn data_id_for_static(
|
|||
"attempt to declare `{symbol_name}` as static, but it was already declared as function"
|
||||
)),
|
||||
Err(err) => Err::<_, _>(err).unwrap(),
|
||||
};
|
||||
|
||||
data_id
|
||||
}
|
||||
}
|
||||
|
||||
fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
|
||||
|
|
@ -368,6 +372,8 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut data = DataDescription::new();
|
||||
|
||||
let (data_id, alloc, section_name) = match todo_item {
|
||||
TodoItem::Alloc(alloc_id) => {
|
||||
let alloc = match tcx.global_alloc(alloc_id) {
|
||||
|
|
@ -386,7 +392,10 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
(data_id, alloc, None)
|
||||
}
|
||||
TodoItem::Static(def_id) => {
|
||||
let section_name = tcx.codegen_fn_attrs(def_id).link_section;
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
let section_name = codegen_fn_attrs.link_section;
|
||||
|
||||
data.set_used(codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER));
|
||||
|
||||
let alloc = tcx.eval_static_initializer(def_id).unwrap();
|
||||
|
||||
|
|
@ -401,7 +410,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
}
|
||||
};
|
||||
|
||||
let mut data = DataDescription::new();
|
||||
let alloc = alloc.inner();
|
||||
data.set_align(alloc.align.bytes());
|
||||
|
||||
|
|
@ -594,7 +602,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||
{
|
||||
return None;
|
||||
}
|
||||
StatementKind::Intrinsic(ref intrinsic) => match **intrinsic {
|
||||
StatementKind::Intrinsic(intrinsic) => match **intrinsic {
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(..) => return None,
|
||||
NonDivergingIntrinsic::Assume(..) => {}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ impl WriterRelocate {
|
|||
if jit_module.declarations().get_function_decl(func_id).name.as_deref()
|
||||
== Some("rust_eh_personality")
|
||||
{
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
fn rust_eh_personality() -> !;
|
||||
}
|
||||
rust_eh_personality as *const u8
|
||||
|
|
@ -222,12 +222,12 @@ impl Writer for WriterRelocate {
|
|||
gimli::DW_EH_PE_absptr => {
|
||||
self.relocs.push(DebugReloc {
|
||||
offset: self.len() as u32,
|
||||
size: size.into(),
|
||||
size,
|
||||
name: DebugRelocName::Symbol(symbol),
|
||||
addend,
|
||||
kind: object::RelocationKind::Absolute,
|
||||
});
|
||||
self.write_udata(0, size.into())
|
||||
self.write_udata(0, size)
|
||||
}
|
||||
_ => Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,271 @@
|
|||
use gimli::write::{Address, Writer};
|
||||
use gimli::{DW_EH_PE_omit, DW_EH_PE_uleb128, Encoding, LittleEndian};
|
||||
|
||||
pub(super) struct GccExceptTable {
|
||||
pub call_sites: CallSiteTable,
|
||||
pub actions: ActionTable,
|
||||
pub type_info: TypeInfoTable,
|
||||
}
|
||||
|
||||
impl GccExceptTable {
|
||||
pub(super) fn write<W: Writer>(
|
||||
&self,
|
||||
w: &mut W,
|
||||
encoding: Encoding,
|
||||
) -> gimli::write::Result<()> {
|
||||
// lpStartEncoding
|
||||
w.write_u8(DW_EH_PE_omit.0)?;
|
||||
// lpStart (omitted)
|
||||
let type_info_padding = if self.type_info.type_info.is_empty() {
|
||||
// ttypeEncoding
|
||||
w.write_u8(DW_EH_PE_omit.0)?;
|
||||
None
|
||||
} else {
|
||||
// ttypeEncoding
|
||||
w.write_u8(self.type_info.ttype_encoding.0)?;
|
||||
|
||||
// classInfoOffset
|
||||
let class_info_offset_field_offset = w.len() as u64;
|
||||
|
||||
// Note: The offset in classInfoOffset is relative to position right after classInfoOffset
|
||||
// itself.
|
||||
let class_info_offset_no_padding = self.call_sites.encoded_size()
|
||||
+ self.actions.encoded_size()
|
||||
+ self.type_info.encoded_size(encoding);
|
||||
|
||||
let type_info_is_aligned = |type_info_padding: u64| {
|
||||
(class_info_offset_field_offset
|
||||
+ gimli::leb128::write::uleb128_size(
|
||||
class_info_offset_no_padding + type_info_padding,
|
||||
) as u64
|
||||
+ self.call_sites.encoded_size()
|
||||
+ self.actions.encoded_size()
|
||||
+ type_info_padding)
|
||||
.is_multiple_of(4)
|
||||
};
|
||||
|
||||
let mut type_info_padding = 0;
|
||||
while !type_info_is_aligned(type_info_padding) {
|
||||
type_info_padding += 1;
|
||||
}
|
||||
|
||||
w.write_uleb128(class_info_offset_no_padding + type_info_padding)?;
|
||||
|
||||
Some(type_info_padding)
|
||||
};
|
||||
|
||||
// call site table
|
||||
self.call_sites.write(w)?;
|
||||
|
||||
// action table
|
||||
self.actions.write(w)?;
|
||||
|
||||
// align to 4 bytes
|
||||
if let Some(type_info_padding) = type_info_padding {
|
||||
for _ in 0..type_info_padding {
|
||||
w.write_u8(0)?;
|
||||
}
|
||||
// In this case we calculated the expected padding amount and used it to write the
|
||||
// classInfoOffset field. Assert that the expected value matched the actual value to catch
|
||||
// any inconsistency.
|
||||
assert!(w.len().is_multiple_of(4), "type_info must be aligned to 4 bytes");
|
||||
} else {
|
||||
while !w.len().is_multiple_of(4) {
|
||||
w.write_u8(0)?;
|
||||
}
|
||||
}
|
||||
|
||||
// type_info
|
||||
self.type_info.write(w, encoding)?;
|
||||
|
||||
// exception specs (unused for rust)
|
||||
|
||||
// align to 4 bytes
|
||||
while !w.len().is_multiple_of(4) {
|
||||
w.write_u8(0)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct CallSiteTable(pub Vec<CallSite>);
|
||||
|
||||
impl CallSiteTable {
|
||||
fn encoded_size(&self) -> u64 {
|
||||
let mut len = LenWriter(0);
|
||||
self.write(&mut len).unwrap();
|
||||
len.0 as u64
|
||||
}
|
||||
|
||||
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
|
||||
let callsite_table_length = self.0.iter().map(|call_site| call_site.encoded_size()).sum();
|
||||
|
||||
// callsiteEncoding
|
||||
w.write_u8(DW_EH_PE_uleb128.0)?;
|
||||
// callsiteTableLength
|
||||
w.write_uleb128(callsite_table_length)?;
|
||||
|
||||
for call_site in &self.0 {
|
||||
call_site.write(w)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct CallSite {
|
||||
pub start: u64,
|
||||
pub length: u64,
|
||||
pub landing_pad: u64,
|
||||
pub action_entry: Option<ActionOffset>,
|
||||
}
|
||||
|
||||
impl CallSite {
|
||||
fn encoded_size(&self) -> u64 {
|
||||
let mut len = LenWriter(0);
|
||||
self.write(&mut len).unwrap();
|
||||
len.0 as u64
|
||||
}
|
||||
|
||||
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
|
||||
w.write_uleb128(self.start)?;
|
||||
w.write_uleb128(self.length)?;
|
||||
w.write_uleb128(self.landing_pad)?;
|
||||
w.write_uleb128(match self.action_entry {
|
||||
Some(action_offset) => action_offset.0 + 1,
|
||||
None => 0,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ActionTable {
|
||||
actions: Vec<Action>,
|
||||
encoded_length: u64,
|
||||
}
|
||||
|
||||
impl ActionTable {
|
||||
pub(super) fn new() -> ActionTable {
|
||||
ActionTable { actions: vec![], encoded_length: 0 }
|
||||
}
|
||||
|
||||
pub(super) fn add(&mut self, action: Action) -> ActionOffset {
|
||||
let id = ActionOffset(self.encoded_length);
|
||||
self.encoded_length += action.encoded_size(self.encoded_length);
|
||||
self.actions.push(action);
|
||||
id
|
||||
}
|
||||
|
||||
fn encoded_size(&self) -> u64 {
|
||||
let mut len = LenWriter(0);
|
||||
self.write(&mut len).unwrap();
|
||||
len.0 as u64
|
||||
}
|
||||
|
||||
fn write<W: Writer>(&self, w: &mut W) -> gimli::write::Result<()> {
|
||||
let action_table_start = w.len() as u64;
|
||||
for action in &self.actions {
|
||||
action.write(w, w.len() as u64 - action_table_start)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(super) struct ActionOffset(u64);
|
||||
|
||||
pub(super) struct Action {
|
||||
pub(super) kind: ActionKind,
|
||||
pub(super) next_action: Option<ActionOffset>,
|
||||
}
|
||||
|
||||
impl Action {
|
||||
fn encoded_size(&self, action_table_offset: u64) -> u64 {
|
||||
let mut len = LenWriter(0);
|
||||
self.write(&mut len, action_table_offset).unwrap();
|
||||
len.0 as u64
|
||||
}
|
||||
|
||||
fn write<W: Writer>(&self, w: &mut W, action_table_offset: u64) -> gimli::write::Result<()> {
|
||||
// ttypeIndex
|
||||
let ttype_index = match self.kind {
|
||||
ActionKind::Catch(type_info_id) => type_info_id.0 as i64 + 1,
|
||||
};
|
||||
w.write_sleb128(ttype_index)?;
|
||||
// actionOffset
|
||||
let action_offset_field_offset =
|
||||
action_table_offset + gimli::leb128::write::sleb128_size(ttype_index) as u64;
|
||||
w.write_sleb128(match self.next_action {
|
||||
Some(next_action_offset) => {
|
||||
next_action_offset.0 as i64 - action_offset_field_offset as i64
|
||||
}
|
||||
None => 0,
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(super) enum ActionKind {
|
||||
Catch(TypeInfoId),
|
||||
}
|
||||
|
||||
pub(super) struct TypeInfoTable {
|
||||
ttype_encoding: gimli::DwEhPe,
|
||||
type_info: Vec<Address>,
|
||||
}
|
||||
|
||||
impl TypeInfoTable {
|
||||
pub(super) fn new(ttype_encoding: gimli::DwEhPe) -> TypeInfoTable {
|
||||
TypeInfoTable { ttype_encoding, type_info: vec![] }
|
||||
}
|
||||
|
||||
pub(super) fn add(&mut self, type_info: Address) -> TypeInfoId {
|
||||
let id = TypeInfoId(self.type_info.len() as u64);
|
||||
self.type_info.push(type_info);
|
||||
id
|
||||
}
|
||||
|
||||
fn encoded_size(&self, encoding: Encoding) -> u64 {
|
||||
let mut len = LenWriter(0);
|
||||
self.write(&mut len, encoding).unwrap();
|
||||
len.0 as u64
|
||||
}
|
||||
|
||||
fn write<W: Writer>(&self, w: &mut W, encoding: Encoding) -> gimli::write::Result<()> {
|
||||
for &type_info in self.type_info.iter().rev() {
|
||||
w.write_eh_pointer(type_info, self.ttype_encoding, encoding.address_size)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub(super) struct TypeInfoId(u64);
|
||||
|
||||
struct LenWriter(usize);
|
||||
|
||||
impl Writer for LenWriter {
|
||||
type Endian = LittleEndian;
|
||||
|
||||
fn endian(&self) -> LittleEndian {
|
||||
LittleEndian
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn write(&mut self, bytes: &[u8]) -> gimli::write::Result<()> {
|
||||
self.0 += bytes.len();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_at(&mut self, offset: usize, bytes: &[u8]) -> gimli::write::Result<()> {
|
||||
assert!(offset + bytes.len() < self.0);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,7 @@ use std::path::{Component, Path};
|
|||
use cranelift_codegen::MachSrcLoc;
|
||||
use cranelift_codegen::binemit::CodeOffset;
|
||||
use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
|
||||
use rustc_span::{
|
||||
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm, hygiene,
|
||||
};
|
||||
use rustc_span::{FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHashAlgorithm, hygiene};
|
||||
|
||||
use crate::debuginfo::FunctionDebugContext;
|
||||
use crate::debuginfo::emit::address_for_func;
|
||||
|
|
@ -44,21 +42,27 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
|
|||
}
|
||||
}
|
||||
|
||||
const MD5_LEN: usize = 16;
|
||||
fn make_file_info(source_file: &SourceFile, embed_source: bool) -> Option<FileInfo> {
|
||||
let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5;
|
||||
let has_source = embed_source && source_file.src.is_some();
|
||||
|
||||
fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
|
||||
if hash.kind == SourceFileHashAlgorithm::Md5 {
|
||||
let mut buf = [0u8; MD5_LEN];
|
||||
buf.copy_from_slice(hash.hash_bytes());
|
||||
Some(FileInfo {
|
||||
timestamp: 0,
|
||||
size: 0,
|
||||
md5: buf,
|
||||
source: None, // FIXME implement -Zembed-source
|
||||
})
|
||||
} else {
|
||||
None
|
||||
if !has_md5 && !has_source {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut info = FileInfo::default();
|
||||
|
||||
if has_md5 {
|
||||
info.md5.copy_from_slice(source_file.src_hash.hash_bytes());
|
||||
}
|
||||
|
||||
if embed_source {
|
||||
if let Some(src) = &source_file.src {
|
||||
info.source = Some(LineString::String(src.as_bytes().to_vec()));
|
||||
}
|
||||
}
|
||||
|
||||
Some(info)
|
||||
}
|
||||
|
||||
impl DebugContext {
|
||||
|
|
@ -105,15 +109,19 @@ impl DebugContext {
|
|||
let file_name =
|
||||
LineString::new(file_name, line_program.encoding(), line_strings);
|
||||
|
||||
let info = make_file_info(source_file.src_hash);
|
||||
let info = make_file_info(source_file, self.embed_source);
|
||||
|
||||
line_program.file_has_md5 &= info.is_some();
|
||||
let has_md5 = source_file.src_hash.kind == SourceFileHashAlgorithm::Md5;
|
||||
line_program.file_has_md5 &= has_md5;
|
||||
line_program.add_file(file_name, dir_id, info)
|
||||
}
|
||||
filename => {
|
||||
let dir_id = line_program.default_directory();
|
||||
// For anonymous sources, create an empty directory instead of using the default
|
||||
let empty_dir = LineString::new(b"", line_program.encoding(), line_strings);
|
||||
let dir_id = line_program.add_directory(empty_dir);
|
||||
|
||||
let dummy_file_name = LineString::new(
|
||||
filename.display(self.filename_display_preference).to_string().into_bytes(),
|
||||
filename.prefer_remapped_unconditionally().to_string().into_bytes(),
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! Handling of everything related to debuginfo.
|
||||
|
||||
mod emit;
|
||||
mod gcc_except_table;
|
||||
mod line_info;
|
||||
mod object;
|
||||
mod types;
|
||||
|
|
@ -19,12 +20,13 @@ use rustc_codegen_ssa::debuginfo::type_names;
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId};
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
pub(crate) use self::emit::{DebugReloc, DebugRelocName};
|
||||
pub(crate) use self::types::TypeDebugContext;
|
||||
pub(crate) use self::unwind::UnwindContext;
|
||||
pub(crate) use self::unwind::{EXCEPTION_HANDLER_CATCH, EXCEPTION_HANDLER_CLEANUP, UnwindContext};
|
||||
use crate::debuginfo::emit::{address_for_data, address_for_func};
|
||||
use crate::prelude::*;
|
||||
|
||||
|
|
@ -43,6 +45,7 @@ pub(crate) struct DebugContext {
|
|||
array_size_type: UnitEntryId,
|
||||
|
||||
filename_display_preference: FileNameDisplayPreference,
|
||||
embed_source: bool,
|
||||
}
|
||||
|
||||
pub(crate) struct FunctionDebugContext {
|
||||
|
|
@ -52,22 +55,37 @@ pub(crate) struct FunctionDebugContext {
|
|||
}
|
||||
|
||||
impl DebugContext {
|
||||
pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self {
|
||||
pub(crate) fn new(
|
||||
tcx: TyCtxt<'_>,
|
||||
isa: &dyn TargetIsa,
|
||||
force_disable_debuginfo: bool,
|
||||
cgu_name: &str,
|
||||
) -> Option<Self> {
|
||||
if tcx.sess.opts.debuginfo == DebugInfo::None
|
||||
|| force_disable_debuginfo
|
||||
|| tcx.sess.target.options.is_like_windows
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut requested_dwarf_version = tcx.sess.dwarf_version();
|
||||
if tcx.sess.target.is_like_darwin && requested_dwarf_version > 4 {
|
||||
// Apple’s shipped debuggers still expect DWARF <= 4 by default.
|
||||
// Stay on v4 unless the user explicitly opts into a feature that
|
||||
// only works with v5 (e.g. -Zembed-source).
|
||||
if !tcx.sess.opts.unstable_opts.embed_source {
|
||||
requested_dwarf_version = 4;
|
||||
}
|
||||
}
|
||||
|
||||
let encoding = Encoding {
|
||||
format: Format::Dwarf32,
|
||||
// FIXME this should be configurable
|
||||
// macOS doesn't seem to support DWARF > 3
|
||||
// 5 version is required for md5 file hash
|
||||
version: if tcx.sess.target.is_like_darwin {
|
||||
3
|
||||
} else {
|
||||
// FIXME change to version 5 once the gdb and lldb shipping with the latest debian
|
||||
// support it.
|
||||
4
|
||||
},
|
||||
version: requested_dwarf_version as u16,
|
||||
address_size: isa.frontend_config().pointer_bytes(),
|
||||
};
|
||||
|
||||
let embed_source = tcx.sess.opts.unstable_opts.embed_source && encoding.version >= 5;
|
||||
|
||||
let endian = match isa.endianness() {
|
||||
Endianness::Little => RunTimeEndian::Little,
|
||||
Endianness::Big => RunTimeEndian::Big,
|
||||
|
|
@ -106,10 +124,14 @@ impl DebugContext {
|
|||
encoding,
|
||||
LineEncoding::default(),
|
||||
LineString::new(comp_dir.as_bytes(), encoding, &mut dwarf.line_strings),
|
||||
None,
|
||||
LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings),
|
||||
file_info,
|
||||
);
|
||||
line_program.file_has_md5 = file_has_md5;
|
||||
if embed_source {
|
||||
line_program.file_has_source = true;
|
||||
}
|
||||
|
||||
dwarf.unit.line_program = line_program;
|
||||
|
||||
|
|
@ -145,7 +167,7 @@ impl DebugContext {
|
|||
AttributeValue::Udata(isa.frontend_config().pointer_bytes().into()),
|
||||
);
|
||||
|
||||
DebugContext {
|
||||
Some(DebugContext {
|
||||
endian,
|
||||
dwarf,
|
||||
unit_range_list: RangeList(Vec::new()),
|
||||
|
|
@ -154,7 +176,8 @@ impl DebugContext {
|
|||
namespace_map: DefIdMap::default(),
|
||||
array_size_type,
|
||||
filename_display_preference,
|
||||
}
|
||||
embed_source,
|
||||
})
|
||||
}
|
||||
|
||||
fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl DebugContext {
|
|||
// ty::FnDef(..) | ty::FnPtr(..)
|
||||
// ty::Closure(..)
|
||||
// ty::Adt(def, ..)
|
||||
ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, *components),
|
||||
ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, components),
|
||||
// ty::Param(_)
|
||||
// FIXME implement remaining types and add unreachable!() to the fallback branch
|
||||
_ => self.placeholder_for_type(tcx, type_dbg, ty),
|
||||
|
|
@ -152,7 +152,7 @@ impl DebugContext {
|
|||
components: &'tcx [Ty<'tcx>],
|
||||
) -> UnitEntryId {
|
||||
let components = components
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|&ty| (ty, self.debug_type(tcx, type_dbg, ty)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,23 @@
|
|||
//! Unwind info generation (`.eh_frame`)
|
||||
|
||||
use cranelift_codegen::FinalizedMachExceptionHandler;
|
||||
use cranelift_codegen::ir::Endianness;
|
||||
use cranelift_codegen::isa::unwind::UnwindInfo;
|
||||
use cranelift_module::DataId;
|
||||
use cranelift_object::ObjectProduct;
|
||||
use gimli::RunTimeEndian;
|
||||
use gimli::write::{CieId, EhFrame, FrameTable, Section};
|
||||
use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
|
||||
use gimli::{Encoding, Format, RunTimeEndian};
|
||||
|
||||
use super::emit::address_for_func;
|
||||
use super::emit::{DebugRelocName, address_for_data, address_for_func};
|
||||
use super::gcc_except_table::{
|
||||
Action, ActionKind, ActionTable, CallSite, CallSiteTable, GccExceptTable, TypeInfoTable,
|
||||
};
|
||||
use super::object::WriteDebugInfo;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub(crate) const EXCEPTION_HANDLER_CLEANUP: u32 = 0;
|
||||
pub(crate) const EXCEPTION_HANDLER_CATCH: u32 = 1;
|
||||
|
||||
pub(crate) struct UnwindContext {
|
||||
endian: RunTimeEndian,
|
||||
frame_table: FrameTable,
|
||||
|
|
@ -25,10 +33,79 @@ impl UnwindContext {
|
|||
let mut frame_table = FrameTable::default();
|
||||
|
||||
let cie_id = if let Some(mut cie) = module.isa().create_systemv_cie() {
|
||||
if pic_eh_frame {
|
||||
cie.fde_address_encoding =
|
||||
gimli::DwEhPe(gimli::DW_EH_PE_pcrel.0 | gimli::DW_EH_PE_sdata4.0);
|
||||
let ptr_encoding = if pic_eh_frame {
|
||||
gimli::DwEhPe(gimli::DW_EH_PE_pcrel.0 | gimli::DW_EH_PE_sdata4.0)
|
||||
} else {
|
||||
gimli::DW_EH_PE_absptr
|
||||
};
|
||||
|
||||
cie.fde_address_encoding = ptr_encoding;
|
||||
|
||||
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
|
||||
if cfg!(feature = "unwinding") {
|
||||
let code_ptr_encoding = if pic_eh_frame {
|
||||
if module.isa().triple().architecture == target_lexicon::Architecture::X86_64 {
|
||||
gimli::DwEhPe(
|
||||
gimli::DW_EH_PE_indirect.0
|
||||
| gimli::DW_EH_PE_pcrel.0
|
||||
| gimli::DW_EH_PE_sdata4.0,
|
||||
)
|
||||
} else if let target_lexicon::Architecture::Aarch64(_) =
|
||||
module.isa().triple().architecture
|
||||
{
|
||||
gimli::DwEhPe(
|
||||
gimli::DW_EH_PE_indirect.0
|
||||
| gimli::DW_EH_PE_pcrel.0
|
||||
| gimli::DW_EH_PE_sdata8.0,
|
||||
)
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
} else {
|
||||
gimli::DwEhPe(gimli::DW_EH_PE_indirect.0 | gimli::DW_EH_PE_absptr.0)
|
||||
};
|
||||
|
||||
cie.lsda_encoding = Some(ptr_encoding);
|
||||
|
||||
// FIXME use eh_personality lang item instead
|
||||
let personality = module
|
||||
.declare_function(
|
||||
"rust_eh_personality",
|
||||
Linkage::Import,
|
||||
&Signature {
|
||||
params: vec![
|
||||
AbiParam::new(types::I32),
|
||||
AbiParam::new(types::I32),
|
||||
AbiParam::new(types::I64),
|
||||
AbiParam::new(module.target_config().pointer_type()),
|
||||
AbiParam::new(module.target_config().pointer_type()),
|
||||
],
|
||||
returns: vec![AbiParam::new(types::I32)],
|
||||
call_conv: module.target_config().default_call_conv,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Use indirection here to support PIC the case where rust_eh_personality is defined in
|
||||
// another DSO.
|
||||
let personality_ref = module
|
||||
.declare_data("DW.ref.rust_eh_personality", Linkage::Local, false, false)
|
||||
.unwrap();
|
||||
|
||||
let mut personality_ref_data = DataDescription::new();
|
||||
// Note: Must not use define_zeroinit. The unwinder can't handle this being in the .bss
|
||||
// section.
|
||||
let pointer_bytes = usize::from(module.target_config().pointer_bytes());
|
||||
personality_ref_data.define(vec![0; pointer_bytes].into_boxed_slice());
|
||||
let personality_func_ref =
|
||||
module.declare_func_in_data(personality, &mut personality_ref_data);
|
||||
personality_ref_data.write_function_addr(0, personality_func_ref);
|
||||
|
||||
module.define_data(personality_ref, &personality_ref_data).unwrap();
|
||||
|
||||
cie.personality = Some((code_ptr_encoding, address_for_data(personality_ref)));
|
||||
}
|
||||
|
||||
Some(frame_table.add_cie(cie))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -63,8 +140,100 @@ impl UnwindContext {
|
|||
|
||||
match unwind_info {
|
||||
UnwindInfo::SystemV(unwind_info) => {
|
||||
self.frame_table
|
||||
.add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id)));
|
||||
let mut fde = unwind_info.to_fde(address_for_func(func_id));
|
||||
|
||||
// FIXME only add personality function and lsda when necessary: https://github.com/rust-lang/rust/blob/1f76d219c906f0112bb1872f33aa977164c53fa6/compiler/rustc_codegen_ssa/src/mir/mod.rs#L200-L204
|
||||
if cfg!(feature = "unwinding") {
|
||||
// FIXME use unique symbol name derived from function name
|
||||
let lsda = module.declare_anonymous_data(false, false).unwrap();
|
||||
|
||||
let encoding = Encoding {
|
||||
format: Format::Dwarf32,
|
||||
version: 1,
|
||||
address_size: module.isa().frontend_config().pointer_bytes(),
|
||||
};
|
||||
|
||||
let mut gcc_except_table_data = GccExceptTable {
|
||||
call_sites: CallSiteTable(vec![]),
|
||||
actions: ActionTable::new(),
|
||||
type_info: TypeInfoTable::new(gimli::DW_EH_PE_udata4),
|
||||
};
|
||||
|
||||
let catch_type = gcc_except_table_data.type_info.add(Address::Constant(0));
|
||||
let catch_action = gcc_except_table_data
|
||||
.actions
|
||||
.add(Action { kind: ActionKind::Catch(catch_type), next_action: None });
|
||||
|
||||
for call_site in context.compiled_code().unwrap().buffer.call_sites() {
|
||||
if call_site.exception_handlers.is_empty() {
|
||||
gcc_except_table_data.call_sites.0.push(CallSite {
|
||||
start: u64::from(call_site.ret_addr - 1),
|
||||
length: 1,
|
||||
landing_pad: 0,
|
||||
action_entry: None,
|
||||
});
|
||||
}
|
||||
for &handler in call_site.exception_handlers {
|
||||
match handler {
|
||||
FinalizedMachExceptionHandler::Tag(tag, landingpad) => {
|
||||
match tag.as_u32() {
|
||||
EXCEPTION_HANDLER_CLEANUP => {
|
||||
gcc_except_table_data.call_sites.0.push(CallSite {
|
||||
start: u64::from(call_site.ret_addr - 1),
|
||||
length: 1,
|
||||
landing_pad: u64::from(landingpad),
|
||||
action_entry: None,
|
||||
})
|
||||
}
|
||||
EXCEPTION_HANDLER_CATCH => {
|
||||
gcc_except_table_data.call_sites.0.push(CallSite {
|
||||
start: u64::from(call_site.ret_addr - 1),
|
||||
length: 1,
|
||||
landing_pad: u64::from(landingpad),
|
||||
action_entry: Some(catch_action),
|
||||
})
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut gcc_except_table = super::emit::WriterRelocate::new(self.endian);
|
||||
|
||||
gcc_except_table_data.write(&mut gcc_except_table, encoding).unwrap();
|
||||
|
||||
let mut data = DataDescription::new();
|
||||
data.define(gcc_except_table.writer.into_vec().into_boxed_slice());
|
||||
data.set_segment_section("", ".gcc_except_table");
|
||||
|
||||
for reloc in &gcc_except_table.relocs {
|
||||
match reloc.name {
|
||||
DebugRelocName::Section(_id) => unreachable!(),
|
||||
DebugRelocName::Symbol(id) => {
|
||||
let id = id.try_into().unwrap();
|
||||
if id & 1 << 31 == 0 {
|
||||
let func_ref = module
|
||||
.declare_func_in_data(FuncId::from_u32(id), &mut data);
|
||||
data.write_function_addr(reloc.offset, func_ref);
|
||||
} else {
|
||||
let gv = module.declare_data_in_data(
|
||||
DataId::from_u32(id & !(1 << 31)),
|
||||
&mut data,
|
||||
);
|
||||
data.write_data_addr(reloc.offset, gv, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.define_data(lsda, &data).unwrap();
|
||||
fde.lsda = Some(address_for_data(lsda));
|
||||
}
|
||||
|
||||
self.frame_table.add_fde(self.cie_id.unwrap(), fde);
|
||||
}
|
||||
UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => {
|
||||
// Windows does not have debug info for its unwind info.
|
||||
|
|
@ -116,7 +285,7 @@ impl UnwindContext {
|
|||
// Everything after this line up to the end of the file is loosely based on
|
||||
// https://github.com/bytecodealliance/wasmtime/blob/4471a82b0c540ff48960eca6757ccce5b1b5c3e4/crates/jit/src/unwind/systemv.rs
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
unsafe {
|
||||
// On macOS, `__register_frame` takes a pointer to a single FDE
|
||||
let start = eh_frame.as_ptr();
|
||||
let end = start.add(eh_frame.len());
|
||||
|
|
@ -138,12 +307,12 @@ impl UnwindContext {
|
|||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
// On other platforms, `__register_frame` will walk the FDEs until an entry of length 0
|
||||
__register_frame(eh_frame.as_ptr());
|
||||
unsafe { __register_frame(eh_frame.as_ptr()) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
// libunwind import
|
||||
fn __register_frame(fde: *const u8);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
|||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{OutFileName, OutputFilenames, OutputType};
|
||||
|
||||
use crate::CodegenCx;
|
||||
use crate::base::CodegenedFunction;
|
||||
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
|
|
@ -98,8 +97,8 @@ impl OngoingCodegen {
|
|||
sess,
|
||||
&module_regular.name,
|
||||
&[
|
||||
("o", &module_regular.object.as_ref().unwrap()),
|
||||
("asm.o", &module_global_asm.object.as_ref().unwrap()),
|
||||
("o", module_regular.object.as_ref().unwrap()),
|
||||
("asm.o", module_global_asm.object.as_ref().unwrap()),
|
||||
],
|
||||
&[],
|
||||
)
|
||||
|
|
@ -107,7 +106,7 @@ impl OngoingCodegen {
|
|||
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
|
||||
sess,
|
||||
&module_regular.name,
|
||||
&[("o", &module_regular.object.as_ref().unwrap())],
|
||||
&[("o", module_regular.object.as_ref().unwrap())],
|
||||
&[],
|
||||
)
|
||||
};
|
||||
|
|
@ -309,7 +308,7 @@ fn produce_final_output_artifacts(
|
|||
module.for_each_output(|path, ty| {
|
||||
if sess.opts.output_types.contains_key(&ty) {
|
||||
let descr = ty.shorthand();
|
||||
sess.dcx().emit_artifact_notification(&path, descr);
|
||||
sess.dcx().emit_artifact_notification(path, descr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -451,8 +450,8 @@ fn reuse_workproduct_for_cgu(
|
|||
tcx.sess.invocation_temp.as_deref(),
|
||||
);
|
||||
let source_file_regular = rustc_incremental::in_incr_comp_dir_sess(
|
||||
&tcx.sess,
|
||||
&work_product.saved_files.get("o").expect("no saved object file in work product"),
|
||||
tcx.sess,
|
||||
work_product.saved_files.get("o").expect("no saved object file in work product"),
|
||||
);
|
||||
|
||||
if let Err(err) = rustc_fs_util::link_or_copy(&source_file_regular, &obj_out_regular) {
|
||||
|
|
@ -467,7 +466,7 @@ fn reuse_workproduct_for_cgu(
|
|||
let obj_out_global_asm =
|
||||
crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm");
|
||||
let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") {
|
||||
let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o);
|
||||
let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(tcx.sess, asm_o);
|
||||
if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm)
|
||||
{
|
||||
return Err(format!(
|
||||
|
|
@ -511,18 +510,14 @@ fn codegen_cgu_content(
|
|||
tcx: TyCtxt<'_>,
|
||||
module: &mut dyn Module,
|
||||
cgu_name: rustc_span::Symbol,
|
||||
) -> (CodegenCx, Vec<CodegenedFunction>) {
|
||||
) -> (Option<DebugContext>, Vec<CodegenedFunction>, String) {
|
||||
let _timer = tcx.prof.generic_activity_with_arg("codegen cgu", cgu_name.as_str());
|
||||
|
||||
let cgu = tcx.codegen_unit(cgu_name);
|
||||
let mono_items = cgu.items_in_deterministic_order(tcx);
|
||||
|
||||
let mut cx = crate::CodegenCx::new(
|
||||
tcx,
|
||||
module.isa(),
|
||||
tcx.sess.opts.debuginfo != DebugInfo::None,
|
||||
cgu_name,
|
||||
);
|
||||
let mut debug_context = DebugContext::new(tcx, module.isa(), false, cgu_name.as_str());
|
||||
let mut global_asm = String::new();
|
||||
let mut type_dbg = TypeDebugContext::default();
|
||||
super::predefine_mono_items(tcx, module, &mono_items);
|
||||
let mut codegened_functions = vec![];
|
||||
|
|
@ -532,7 +527,7 @@ fn codegen_cgu_content(
|
|||
let flags = tcx.codegen_instance_attrs(instance.def).flags;
|
||||
if flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut global_asm },
|
||||
instance,
|
||||
MonoItemData {
|
||||
linkage: RLinkage::External,
|
||||
|
|
@ -548,7 +543,8 @@ fn codegen_cgu_content(
|
|||
}
|
||||
let codegened_function = crate::base::codegen_fn(
|
||||
tcx,
|
||||
&mut cx,
|
||||
cgu_name,
|
||||
debug_context.as_mut(),
|
||||
&mut type_dbg,
|
||||
Function::new(),
|
||||
module,
|
||||
|
|
@ -558,13 +554,13 @@ fn codegen_cgu_content(
|
|||
}
|
||||
MonoItem::Static(def_id) => {
|
||||
let data_id = crate::constant::codegen_static(tcx, module, def_id);
|
||||
if let Some(debug_context) = &mut cx.debug_context {
|
||||
if let Some(debug_context) = debug_context.as_mut() {
|
||||
debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
|
||||
}
|
||||
}
|
||||
MonoItem::GlobalAsm(item_id) => {
|
||||
rustc_codegen_ssa::base::codegen_global_asm(
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
|
||||
&mut GlobalAsmContext { tcx, global_asm: &mut global_asm },
|
||||
item_id,
|
||||
);
|
||||
}
|
||||
|
|
@ -572,7 +568,7 @@ fn codegen_cgu_content(
|
|||
}
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, module, false, cgu.is_primary());
|
||||
|
||||
(cx, codegened_functions)
|
||||
(debug_context, codegened_functions, global_asm)
|
||||
}
|
||||
|
||||
fn module_codegen(
|
||||
|
|
@ -585,13 +581,17 @@ fn module_codegen(
|
|||
) -> OngoingModuleCodegen {
|
||||
let mut module = make_module(tcx.sess, cgu_name.as_str().to_string());
|
||||
|
||||
let (mut cx, codegened_functions) = codegen_cgu_content(tcx, &mut module, cgu_name);
|
||||
let (mut debug_context, codegened_functions, mut global_asm) =
|
||||
codegen_cgu_content(tcx, &mut module, cgu_name);
|
||||
|
||||
let cgu_name = cgu_name.as_str().to_owned();
|
||||
|
||||
let producer = crate::debuginfo::producer(tcx.sess);
|
||||
|
||||
let profiler = tcx.prof.clone();
|
||||
let invocation_temp = tcx.sess.invocation_temp.clone();
|
||||
let output_filenames = tcx.output_filenames(()).clone();
|
||||
let should_write_ir = crate::pretty_clif::should_write_ir(tcx.sess);
|
||||
|
||||
OngoingModuleCodegen::Async(std::thread::spawn(move || {
|
||||
profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| {
|
||||
|
|
@ -602,10 +602,13 @@ fn module_codegen(
|
|||
let mut cached_context = Context::new();
|
||||
for codegened_func in codegened_functions {
|
||||
crate::base::compile_fn(
|
||||
&mut cx,
|
||||
&profiler,
|
||||
&output_filenames,
|
||||
should_write_ir,
|
||||
&mut cached_context,
|
||||
&mut module,
|
||||
debug_context.as_mut(),
|
||||
&mut global_asm,
|
||||
codegened_func,
|
||||
);
|
||||
}
|
||||
|
|
@ -616,8 +619,8 @@ fn module_codegen(
|
|||
crate::global_asm::compile_global_asm(
|
||||
&global_asm_config,
|
||||
&cgu_name,
|
||||
&cx.global_asm,
|
||||
cx.invocation_temp.as_deref(),
|
||||
global_asm,
|
||||
invocation_temp.as_deref(),
|
||||
)
|
||||
})?;
|
||||
|
||||
|
|
@ -625,11 +628,11 @@ fn module_codegen(
|
|||
profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
|
||||
emit_cgu(
|
||||
&global_asm_config.output_filenames,
|
||||
cx.invocation_temp.as_deref(),
|
||||
invocation_temp.as_deref(),
|
||||
&profiler,
|
||||
cgu_name,
|
||||
module,
|
||||
cx.debug_context,
|
||||
debug_context,
|
||||
global_asm_object_file,
|
||||
&producer,
|
||||
)
|
||||
|
|
@ -681,7 +684,7 @@ pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
|
|||
|
||||
// Calculate the CGU reuse
|
||||
let cgu_reuse = tcx.sess.time("find_cgu_reuse", || {
|
||||
cgus.iter().map(|cgu| determine_cgu_reuse(tcx, &cgu)).collect::<Vec<_>>()
|
||||
cgus.iter().map(|cgu| determine_cgu_reuse(tcx, cgu)).collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
rustc_codegen_ssa::assert_module_sources::assert_module_sources(tcx, &|cgu_reuse_tracker| {
|
||||
|
|
@ -695,7 +698,7 @@ pub(crate) fn run_aot(tcx: TyCtxt<'_>) -> Box<OngoingCodegen> {
|
|||
|
||||
let disable_incr_cache = disable_incr_cache();
|
||||
let (todo_cgus, done_cgus) =
|
||||
cgus.into_iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
|
||||
cgus.iter().enumerate().partition::<Vec<_>, _>(|&(i, _)| match cgu_reuse[i] {
|
||||
_ if disable_incr_cache => true,
|
||||
CguReuse::No => true,
|
||||
CguReuse::PreLto | CguReuse::PostLto => false,
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ use rustc_codegen_ssa::CrateInfo;
|
|||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::OutputFilenames;
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::CodegenCx;
|
||||
use crate::debuginfo::TypeDebugContext;
|
||||
use crate::prelude::*;
|
||||
use crate::unwind_module::UnwindModule;
|
||||
|
||||
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
|
||||
fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, Option<DebugContext>) {
|
||||
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
|
||||
|
||||
let isa = crate::build_isa(tcx.sess, true);
|
||||
|
|
@ -25,7 +25,7 @@ fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
|
|||
jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
|
||||
let mut jit_module = UnwindModule::new(JITModule::new(jit_builder), false);
|
||||
|
||||
let cx = crate::CodegenCx::new(tcx, jit_module.isa(), false, sym::dummy_cgu_name);
|
||||
let cx = DebugContext::new(tcx, jit_module.isa(), false, "dummy_cgu_name");
|
||||
|
||||
crate::allocator::codegen(tcx, &mut jit_module);
|
||||
|
||||
|
|
@ -33,13 +33,13 @@ fn create_jit_module(tcx: TyCtxt<'_>) -> (UnwindModule<JITModule>, CodegenCx) {
|
|||
}
|
||||
|
||||
pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
|
||||
// FIXME error on check mode or crate types other than bin in CodegenBackend::init()
|
||||
|
||||
if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) {
|
||||
tcx.dcx().fatal("can't jit non-executable crate");
|
||||
}
|
||||
|
||||
let (mut jit_module, mut cx) = create_jit_module(tcx);
|
||||
let output_filenames = tcx.output_filenames(());
|
||||
let should_write_ir = crate::pretty_clif::should_write_ir(tcx.sess);
|
||||
let (mut jit_module, mut debug_context) = create_jit_module(tcx);
|
||||
let mut cached_context = Context::new();
|
||||
|
||||
let cgus = tcx.collect_and_partition_mono_items(()).codegen_units;
|
||||
|
|
@ -58,7 +58,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
|
|||
MonoItem::Fn(inst) => {
|
||||
codegen_and_compile_fn(
|
||||
tcx,
|
||||
&mut cx,
|
||||
&output_filenames,
|
||||
should_write_ir,
|
||||
debug_context.as_mut(),
|
||||
&mut cached_context,
|
||||
&mut jit_module,
|
||||
inst,
|
||||
|
|
@ -75,10 +77,6 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
|
|||
}
|
||||
});
|
||||
|
||||
if !cx.global_asm.is_empty() {
|
||||
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
|
||||
}
|
||||
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, true, true);
|
||||
|
||||
tcx.dcx().abort_if_errors();
|
||||
|
|
@ -120,7 +118,9 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, jit_args: Vec<String>) -> ! {
|
|||
|
||||
fn codegen_and_compile_fn<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
cx: &mut crate::CodegenCx,
|
||||
output_filenames: &OutputFilenames,
|
||||
should_write_ir: bool,
|
||||
mut debug_context: Option<&mut DebugContext>,
|
||||
cached_context: &mut Context,
|
||||
module: &mut dyn Module,
|
||||
instance: Instance<'tcx>,
|
||||
|
|
@ -141,13 +141,28 @@ fn codegen_and_compile_fn<'tcx>(
|
|||
let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
|
||||
let codegened_func = crate::base::codegen_fn(
|
||||
tcx,
|
||||
cx,
|
||||
sym::dummy_cgu_name,
|
||||
debug_context.as_deref_mut(),
|
||||
&mut TypeDebugContext::default(),
|
||||
cached_func,
|
||||
module,
|
||||
instance,
|
||||
);
|
||||
crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func);
|
||||
|
||||
let mut global_asm = String::new();
|
||||
crate::base::compile_fn(
|
||||
&tcx.prof,
|
||||
output_filenames,
|
||||
should_write_ir,
|
||||
cached_context,
|
||||
module,
|
||||
debug_context.as_deref_mut(),
|
||||
&mut global_asm,
|
||||
codegened_func,
|
||||
);
|
||||
if !global_asm.is_empty() {
|
||||
tcx.dcx().fatal("Inline asm is not supported in JIT mode");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,16 +38,12 @@ fn predefine_mono_items<'tcx>(
|
|||
.codegen_instance_attrs(instance.def)
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::NAKED);
|
||||
module
|
||||
.declare_function(
|
||||
name,
|
||||
// Naked functions are defined in a separate object
|
||||
// file from the codegen unit rustc expects them to
|
||||
// be defined in.
|
||||
if is_naked { Linkage::Import } else { linkage },
|
||||
&sig,
|
||||
)
|
||||
.unwrap();
|
||||
if is_naked {
|
||||
// Naked functions are defined in a separate object
|
||||
// file, so they can be declared on the fly.
|
||||
continue;
|
||||
}
|
||||
module.declare_function(name, linkage, &sig).unwrap();
|
||||
}
|
||||
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ impl GlobalAsmConfig {
|
|||
pub(crate) fn compile_global_asm(
|
||||
config: &GlobalAsmConfig,
|
||||
cgu_name: &str,
|
||||
global_asm: &str,
|
||||
global_asm: String,
|
||||
invocation_temp: Option<&str>,
|
||||
) -> Result<Option<PathBuf>, String> {
|
||||
if global_asm.is_empty() {
|
||||
|
|
@ -205,6 +205,9 @@ pub(crate) fn compile_global_asm(
|
|||
return Err(format!("Failed to assemble `{}`", global_asm));
|
||||
}
|
||||
} else {
|
||||
// Escape { and }
|
||||
let global_asm = global_asm.replace('{', "{{").replace('}', "}}");
|
||||
|
||||
let mut child = Command::new(std::env::current_exe().unwrap())
|
||||
// Avoid a warning about the jobserver fd not being passed
|
||||
.env_remove("CARGO_MAKEFLAGS")
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
|||
use rustc_hir::LangItem;
|
||||
use rustc_span::sym;
|
||||
use rustc_target::asm::*;
|
||||
use rustc_target::spec::Arch;
|
||||
use target_lexicon::BinaryFormat;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
|
@ -51,6 +52,26 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
if fx.tcx.sess.target.arch == Arch::S390x
|
||||
&& template.len() == 3
|
||||
&& template[0] == InlineAsmTemplatePiece::String("stfle 0(".into())
|
||||
&& let InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: None, span: _ } =
|
||||
template[1]
|
||||
&& template[2] == InlineAsmTemplatePiece::String(")".into())
|
||||
{
|
||||
// FIXME no inline asm support for s390x yet, but stdarch needs it for feature detection
|
||||
match destination {
|
||||
Some(destination) => {
|
||||
let destination_block = fx.get_block(destination);
|
||||
fx.bcx.ins().jump(destination_block, &[]);
|
||||
}
|
||||
None => {
|
||||
fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let operands = operands
|
||||
.iter()
|
||||
.map(|operand| match *operand {
|
||||
|
|
@ -103,11 +124,12 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
|
|||
// be exported from the main codegen unit and may thus be unreachable from the
|
||||
// object file created by an external assembler.
|
||||
let wrapper_name = format!(
|
||||
"__inline_asm_{}_wrapper_n{}",
|
||||
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
|
||||
fx.cx.inline_asm_index
|
||||
"{}__inline_asm_{}_wrapper_n{}",
|
||||
fx.symbol_name,
|
||||
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
|
||||
fx.inline_asm_index,
|
||||
);
|
||||
fx.cx.inline_asm_index += 1;
|
||||
fx.inline_asm_index += 1;
|
||||
let sig =
|
||||
get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
|
||||
create_wrapper_function(fx.module, sig, &wrapper_name, symbol.name);
|
||||
|
|
@ -166,14 +188,15 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
|
|||
asm_gen.allocate_stack_slots();
|
||||
|
||||
let asm_name = format!(
|
||||
"__inline_asm_{}_n{}",
|
||||
fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
|
||||
fx.cx.inline_asm_index
|
||||
"{}__inline_asm_{}_n{}",
|
||||
fx.symbol_name,
|
||||
fx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
|
||||
fx.inline_asm_index,
|
||||
);
|
||||
fx.cx.inline_asm_index += 1;
|
||||
fx.inline_asm_index += 1;
|
||||
|
||||
let generated_asm = asm_gen.generate_asm_wrapper(&asm_name);
|
||||
fx.cx.global_asm.push_str(&generated_asm);
|
||||
fx.inline_asm.push_str(&generated_asm);
|
||||
|
||||
let mut inputs = Vec::new();
|
||||
let mut outputs = Vec::new();
|
||||
|
|
@ -546,20 +569,6 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
|
|||
.emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
|
||||
.unwrap(),
|
||||
},
|
||||
InlineAsmArch::AArch64 => match reg {
|
||||
InlineAsmReg::AArch64(reg) if reg.vreg_index().is_some() => {
|
||||
// rustc emits v0 rather than q0
|
||||
reg.emit(
|
||||
&mut generated_asm,
|
||||
InlineAsmArch::AArch64,
|
||||
Some(modifier.unwrap_or('q')),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
_ => reg
|
||||
.emit(&mut generated_asm, InlineAsmArch::AArch64, *modifier)
|
||||
.unwrap(),
|
||||
},
|
||||
_ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
|
||||
}
|
||||
}
|
||||
|
|
@ -827,6 +836,7 @@ fn call_inline_asm<'tcx>(
|
|||
}
|
||||
|
||||
let stack_slot_addr = stack_slot.get_addr(fx);
|
||||
// FIXME use try_call once unwinding inline assembly is supported
|
||||
fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]);
|
||||
|
||||
for (offset, place) in outputs {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
macro_rules! intrinsic_args {
|
||||
($fx:expr, $args:expr => ($($arg:tt),*); $intrinsic:expr) => {
|
||||
#[allow(unused_parens)]
|
||||
#[allow(unused_parens, clippy::unused_unit)]
|
||||
let ($($arg),*) = if let [$($arg),*] = $args {
|
||||
($(codegen_operand($fx, &($arg).node)),*)
|
||||
} else {
|
||||
|
|
@ -17,17 +17,21 @@ mod llvm_aarch64;
|
|||
mod llvm_x86;
|
||||
mod simd;
|
||||
|
||||
use cranelift_codegen::ir::AtomicRmwOp;
|
||||
use cranelift_codegen::ir::{
|
||||
AtomicRmwOp, BlockArg, ExceptionTableData, ExceptionTableItem, ExceptionTag,
|
||||
};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::layout::ValidityRequirement;
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
|
||||
use crate::cast::clif_intcast;
|
||||
use crate::codegen_f16_f128;
|
||||
use crate::debuginfo::EXCEPTION_HANDLER_CATCH;
|
||||
use crate::prelude::*;
|
||||
|
||||
fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! {
|
||||
|
|
@ -479,7 +483,7 @@ fn codegen_float_intrinsic_call<'tcx>(
|
|||
};
|
||||
let input_tys: Vec<_> =
|
||||
vec![AbiParam::new(clif_ty), lib_call_arg_param(fx.tcx, types::I32, true)];
|
||||
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
|
||||
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0];
|
||||
let ret_val = if intrinsic == sym::powif16 {
|
||||
codegen_f16_f128::f32_to_f16(fx, ret_val)
|
||||
} else {
|
||||
|
|
@ -501,7 +505,7 @@ fn codegen_float_intrinsic_call<'tcx>(
|
|||
}
|
||||
_ => {
|
||||
let input_tys: Vec<_> = args.iter().map(|_| AbiParam::new(clif_ty)).collect();
|
||||
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], &args)[0];
|
||||
let ret_val = fx.lib_call(name, input_tys, vec![AbiParam::new(clif_ty)], args)[0];
|
||||
CValue::by_val(ret_val, fx.layout_of(ty))
|
||||
}
|
||||
};
|
||||
|
|
@ -1337,23 +1341,75 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
|||
}
|
||||
|
||||
sym::catch_unwind => {
|
||||
let ret_block = fx.get_block(destination.unwrap());
|
||||
|
||||
intrinsic_args!(fx, args => (f, data, catch_fn); intrinsic);
|
||||
let f = f.load_scalar(fx);
|
||||
let data = data.load_scalar(fx);
|
||||
let _catch_fn = catch_fn.load_scalar(fx);
|
||||
let catch_fn = catch_fn.load_scalar(fx);
|
||||
|
||||
// FIXME once unwinding is supported, change this to actually catch panics
|
||||
let f_sig = fx.bcx.func.import_signature(Signature {
|
||||
call_conv: fx.target_config.default_call_conv,
|
||||
params: vec![AbiParam::new(pointer_ty(fx.tcx))],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
|
||||
if cfg!(not(feature = "unwinding"))
|
||||
|| fx.tcx.sess.panic_strategy() == PanicStrategy::Abort
|
||||
{
|
||||
fx.bcx.ins().call_indirect(f_sig, f, &[data]);
|
||||
|
||||
let layout = fx.layout_of(fx.tcx.types.i32);
|
||||
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
|
||||
ret.write_cvalue(fx, ret_val);
|
||||
let layout = fx.layout_of(fx.tcx.types.i32);
|
||||
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
|
||||
ret.write_cvalue(fx, ret_val);
|
||||
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
} else {
|
||||
let catch_fn_sig = fx.bcx.func.import_signature(Signature {
|
||||
call_conv: fx.target_config.default_call_conv,
|
||||
params: vec![
|
||||
AbiParam::new(pointer_ty(fx.tcx)),
|
||||
AbiParam::new(pointer_ty(fx.tcx)),
|
||||
],
|
||||
returns: vec![],
|
||||
});
|
||||
|
||||
let fallthrough_block = fx.bcx.create_block();
|
||||
let fallthrough_block_call = fx.bcx.func.dfg.block_call(fallthrough_block, &[]);
|
||||
let catch_block = fx.bcx.create_block();
|
||||
let catch_block_call =
|
||||
fx.bcx.func.dfg.block_call(catch_block, &[BlockArg::TryCallExn(0)]);
|
||||
let exception_table =
|
||||
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
|
||||
f_sig,
|
||||
fallthrough_block_call,
|
||||
[ExceptionTableItem::Tag(
|
||||
ExceptionTag::with_number(EXCEPTION_HANDLER_CATCH).unwrap(),
|
||||
catch_block_call,
|
||||
)],
|
||||
));
|
||||
|
||||
fx.bcx.ins().try_call_indirect(f, &[data], exception_table);
|
||||
|
||||
fx.bcx.seal_block(fallthrough_block);
|
||||
fx.bcx.switch_to_block(fallthrough_block);
|
||||
let layout = fx.layout_of(fx.tcx.types.i32);
|
||||
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout);
|
||||
ret.write_cvalue(fx, ret_val);
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
|
||||
fx.bcx.seal_block(catch_block);
|
||||
fx.bcx.switch_to_block(catch_block);
|
||||
fx.bcx.set_cold_block(catch_block);
|
||||
let exception = fx.bcx.append_block_param(catch_block, pointer_ty(fx.tcx));
|
||||
fx.bcx.ins().call_indirect(catch_fn_sig, catch_fn, &[data, exception]);
|
||||
let layout = fx.layout_of(fx.tcx.types.i32);
|
||||
let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 1), layout);
|
||||
ret.write_cvalue(fx, ret_val);
|
||||
fx.bcx.ins().jump(ret_block, &[]);
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
sym::fadd_fast
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
use rustc_abi::Endian;
|
||||
use rustc_middle::ty::SimdAlign;
|
||||
|
||||
use super::*;
|
||||
use crate::prelude::*;
|
||||
|
|
@ -812,7 +813,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
Endian::Big => lane_count - 1 - lane,
|
||||
Endian::Little => lane,
|
||||
};
|
||||
let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(mask_lane) as i64);
|
||||
let m_lane = fx.bcx.ins().ushr_imm(m, mask_lane.cast_signed());
|
||||
let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
|
||||
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
|
||||
let b_lane = b.value_lane(fx, lane).load_scalar(fx);
|
||||
|
|
@ -960,6 +961,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
|
||||
let ptr_val = ptr.load_scalar(fx);
|
||||
|
||||
let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
|
||||
.unwrap_leaf()
|
||||
.to_simd_alignment();
|
||||
|
||||
let memflags = match alignment {
|
||||
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
|
||||
_ => MemFlags::trusted(),
|
||||
};
|
||||
|
||||
for lane_idx in 0..val_lane_count {
|
||||
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
|
|
@ -972,7 +982,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
|
||||
fx.bcx.switch_to_block(if_enabled);
|
||||
let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32;
|
||||
fx.bcx.ins().store(MemFlags::trusted(), val_lane, ptr_val, Offset32::new(offset));
|
||||
fx.bcx.ins().store(memflags, val_lane, ptr_val, Offset32::new(offset));
|
||||
fx.bcx.ins().jump(next, &[]);
|
||||
|
||||
fx.bcx.seal_block(next);
|
||||
|
|
@ -996,6 +1006,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
let lane_clif_ty = fx.clif_type(val_lane_ty).unwrap();
|
||||
let ret_lane_layout = fx.layout_of(ret_lane_ty);
|
||||
|
||||
let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
|
||||
.unwrap_leaf()
|
||||
.to_simd_alignment();
|
||||
|
||||
let memflags = match alignment {
|
||||
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
|
||||
_ => MemFlags::trusted(),
|
||||
};
|
||||
|
||||
for lane_idx in 0..ptr_lane_count {
|
||||
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
let ptr_lane = ptr.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
|
|
@ -1011,7 +1030,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
fx.bcx.seal_block(if_disabled);
|
||||
|
||||
fx.bcx.switch_to_block(if_enabled);
|
||||
let res = fx.bcx.ins().load(lane_clif_ty, MemFlags::trusted(), ptr_lane, 0);
|
||||
let res = fx.bcx.ins().load(lane_clif_ty, memflags, ptr_lane, 0);
|
||||
fx.bcx.ins().jump(next, &[res.into()]);
|
||||
|
||||
fx.bcx.switch_to_block(if_disabled);
|
||||
|
|
@ -1040,6 +1059,15 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
let ret_lane_layout = fx.layout_of(ret_lane_ty);
|
||||
let ptr_val = ptr.load_scalar(fx);
|
||||
|
||||
let alignment = generic_args[3].expect_const().to_value().valtree.unwrap_branch()[0]
|
||||
.unwrap_leaf()
|
||||
.to_simd_alignment();
|
||||
|
||||
let memflags = match alignment {
|
||||
SimdAlign::Unaligned => MemFlags::new().with_notrap(),
|
||||
_ => MemFlags::trusted(),
|
||||
};
|
||||
|
||||
for lane_idx in 0..ret_lane_count {
|
||||
let val_lane = val.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
let mask_lane = mask.value_lane(fx, lane_idx).load_scalar(fx);
|
||||
|
|
@ -1055,12 +1083,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||
|
||||
fx.bcx.switch_to_block(if_enabled);
|
||||
let offset = lane_idx as i32 * lane_clif_ty.bytes() as i32;
|
||||
let res = fx.bcx.ins().load(
|
||||
lane_clif_ty,
|
||||
MemFlags::trusted(),
|
||||
ptr_val,
|
||||
Offset32::new(offset),
|
||||
);
|
||||
let res = fx.bcx.ins().load(lane_clif_ty, memflags, ptr_val, Offset32::new(offset));
|
||||
fx.bcx.ins().jump(next, &[res.into()]);
|
||||
|
||||
fx.bcx.switch_to_block(if_disabled);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(doc, allow(internal_features))]
|
||||
#![cfg_attr(doc, doc(rust_logo))]
|
||||
#![cfg_attr(doc, feature(rustdoc_internals))]
|
||||
// Note: please avoid adding other feature gates where possible
|
||||
#![feature(rustc_private)]
|
||||
// Only used to define intrinsics in `compiler_builtins.rs`.
|
||||
|
|
@ -20,6 +17,7 @@ extern crate rustc_middle;
|
|||
extern crate rustc_abi;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_codegen_ssa;
|
||||
extern crate rustc_const_eval;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_fs_util;
|
||||
|
|
@ -38,6 +36,7 @@ extern crate rustc_target;
|
|||
extern crate rustc_driver;
|
||||
|
||||
use std::any::Any;
|
||||
use std::cell::OnceCell;
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -50,6 +49,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
|||
use rustc_session::Session;
|
||||
use rustc_session::config::OutputFilenames;
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_target::spec::Arch;
|
||||
|
||||
pub use crate::config::*;
|
||||
use crate::prelude::*;
|
||||
|
|
@ -122,41 +122,8 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The codegen context holds any information shared between the codegen of individual functions
|
||||
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
|
||||
struct CodegenCx {
|
||||
output_filenames: Arc<OutputFilenames>,
|
||||
invocation_temp: Option<String>,
|
||||
should_write_ir: bool,
|
||||
global_asm: String,
|
||||
inline_asm_index: usize,
|
||||
debug_context: Option<DebugContext>,
|
||||
cgu_name: Symbol,
|
||||
}
|
||||
|
||||
impl CodegenCx {
|
||||
fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, debug_info: bool, cgu_name: Symbol) -> Self {
|
||||
assert_eq!(pointer_ty(tcx), isa.pointer_type());
|
||||
|
||||
let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
|
||||
Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
CodegenCx {
|
||||
output_filenames: tcx.output_filenames(()).clone(),
|
||||
invocation_temp: tcx.sess.invocation_temp.clone(),
|
||||
should_write_ir: crate::pretty_clif::should_write_ir(tcx),
|
||||
global_asm: String::new(),
|
||||
inline_asm_index: 0,
|
||||
debug_context,
|
||||
cgu_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CraneliftCodegenBackend {
|
||||
pub config: Option<BackendConfig>,
|
||||
pub config: OnceCell<BackendConfig>,
|
||||
}
|
||||
|
||||
impl CodegenBackend for CraneliftCodegenBackend {
|
||||
|
|
@ -182,58 +149,54 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
sess.dcx()
|
||||
.fatal("`-Cinstrument-coverage` is LLVM specific and not supported by Cranelift");
|
||||
}
|
||||
|
||||
let config = self.config.get_or_init(|| {
|
||||
BackendConfig::from_opts(&sess.opts.cg.llvm_args)
|
||||
.unwrap_or_else(|err| sess.dcx().fatal(err))
|
||||
});
|
||||
|
||||
if config.jit_mode && !sess.opts.output_types.should_codegen() {
|
||||
sess.dcx().fatal("JIT mode doesn't work with `cargo check`");
|
||||
}
|
||||
}
|
||||
|
||||
fn target_config(&self, sess: &Session) -> TargetConfig {
|
||||
// FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
|
||||
let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
|
||||
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
|
||||
vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")]
|
||||
} else if sess.target.arch == "aarch64" {
|
||||
match &*sess.target.os {
|
||||
let target_features = match sess.target.arch {
|
||||
Arch::X86_64 if sess.target.os != "none" => {
|
||||
// x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
|
||||
vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")]
|
||||
}
|
||||
Arch::AArch64 => match &*sess.target.os {
|
||||
"none" => vec![],
|
||||
// On macOS the aes, sha2 and sha3 features are enabled by default and ring
|
||||
// fails to compile on macOS when they are not present.
|
||||
"macos" => vec![sym::neon, sym::aes, sym::sha2, sym::sha3],
|
||||
// AArch64 mandates Neon support
|
||||
_ => vec![sym::neon],
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
_ => vec![],
|
||||
};
|
||||
// FIXME do `unstable_target_features` properly
|
||||
let unstable_target_features = target_features.clone();
|
||||
|
||||
// FIXME(f16_f128): LLVM 20 (currently used by `rustc`) passes `f128` in XMM registers on
|
||||
// Windows, whereas LLVM 21+ and Cranelift pass it indirectly. This means that `f128` won't
|
||||
// work when linking against a LLVM-built sysroot.
|
||||
let has_reliable_f128 = !sess.target.is_like_windows;
|
||||
let has_reliable_f16 = match &*sess.target.arch {
|
||||
// FIXME(f16_f128): LLVM 20 does not support `f16` on s390x, meaning the required
|
||||
// builtins are not available in `compiler-builtins`.
|
||||
"s390x" => false,
|
||||
// FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU
|
||||
// targets due to GCC using a different ABI than LLVM. Therefore `f16` won't be
|
||||
// available when using a LLVM-built sysroot.
|
||||
"x86_64"
|
||||
if sess.target.os == "windows"
|
||||
&& sess.target.env == "gnu"
|
||||
&& sess.target.abi != "llvm" =>
|
||||
{
|
||||
false
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
// FIXME(f16_f128): `rustc_codegen_llvm` currently disables support on Windows GNU
|
||||
// targets due to GCC using a different ABI than LLVM. Therefore `f16` and `f128`
|
||||
// won't be available when using a LLVM-built sysroot.
|
||||
let has_reliable_f16_f128 = !(sess.target.arch == Arch::X86_64
|
||||
&& sess.target.os == "windows"
|
||||
&& sess.target.env == "gnu"
|
||||
&& sess.target.abi != "llvm");
|
||||
|
||||
TargetConfig {
|
||||
target_features,
|
||||
unstable_target_features,
|
||||
// `rustc_codegen_cranelift` polyfills functionality not yet
|
||||
// available in Cranelift.
|
||||
has_reliable_f16,
|
||||
has_reliable_f16_math: has_reliable_f16,
|
||||
has_reliable_f128,
|
||||
has_reliable_f128_math: has_reliable_f128,
|
||||
has_reliable_f16: has_reliable_f16_f128,
|
||||
has_reliable_f16_math: has_reliable_f16_f128,
|
||||
has_reliable_f128: has_reliable_f16_f128,
|
||||
has_reliable_f128_math: has_reliable_f16_f128,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -243,13 +206,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
|||
|
||||
fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> {
|
||||
info!("codegen crate {}", tcx.crate_name(LOCAL_CRATE));
|
||||
let config = self.config.clone().unwrap_or_else(|| {
|
||||
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
|
||||
.unwrap_or_else(|err| tcx.sess.dcx().fatal(err))
|
||||
});
|
||||
let config = self.config.get().unwrap();
|
||||
if config.jit_mode {
|
||||
#[cfg(feature = "jit")]
|
||||
driver::jit::run_jit(tcx, config.jit_args);
|
||||
driver::jit::run_jit(tcx, config.jit_args.clone());
|
||||
|
||||
#[cfg(not(feature = "jit"))]
|
||||
tcx.dcx().fatal("jit support was disabled when compiling rustc_codegen_cranelift");
|
||||
|
|
@ -296,8 +256,8 @@ fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
|
|||
flags_builder.set("enable_verifier", enable_verifier).unwrap();
|
||||
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
|
||||
|
||||
let mut frame_ptr = sess.target.options.frame_pointer.clone();
|
||||
frame_ptr.ratchet(sess.opts.cg.force_frame_pointers);
|
||||
let frame_ptr =
|
||||
{ sess.target.options.frame_pointer }.ratchet(sess.opts.cg.force_frame_pointers);
|
||||
let preserve_frame_pointer = frame_ptr != rustc_target::spec::FramePointer::MayOmit;
|
||||
flags_builder
|
||||
.set("preserve_frame_pointers", if preserve_frame_pointer { "true" } else { "false" })
|
||||
|
|
@ -393,7 +353,7 @@ fn build_isa(sess: &Session, jit: bool) -> Arc<dyn TargetIsa + 'static> {
|
|||
}
|
||||
|
||||
/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
|
||||
Box::new(CraneliftCodegenBackend { config: None })
|
||||
Box::new(CraneliftCodegenBackend { config: OnceCell::new() })
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue