Merge branch 'master' into abi

This commit is contained in:
Stefan Lankes 2020-04-04 07:41:05 +02:00 committed by GitHub
commit aa223304dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1103 changed files with 11605 additions and 10113 deletions

View File

@ -14,7 +14,7 @@ http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
### Code
```
```Rust
<code>
```

View File

@ -63,7 +63,7 @@ jobs:
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
with:
github_token: "${{ secrets.github_token }}"
if: success() && !env.SKIP_JOB
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
- name: add extra environment variables
run: src/ci/scripts/setup-environment.sh
env:
@ -196,7 +196,7 @@ jobs:
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
with:
github_token: "${{ secrets.github_token }}"
if: success() && !env.SKIP_JOB
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
- name: add extra environment variables
run: src/ci/scripts/setup-environment.sh
env:
@ -626,7 +626,7 @@ jobs:
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
with:
github_token: "${{ secrets.github_token }}"
if: success() && !env.SKIP_JOB
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
- name: add extra environment variables
run: src/ci/scripts/setup-environment.sh
env:

View File

@ -2522,9 +2522,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "polonius-engine"
version = "0.12.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04d8ef65e3f89ecaec9ca7cb0e0911b4617352d4494018bcf934992f03f2024c"
checksum = "ef2558a4b464e185b36ee08a2937ebb62ea5464c38856cfb1465c97cb38db52d"
dependencies = [
"datafrog",
"log",
@ -3132,39 +3132,6 @@ dependencies = [
"rustc-workspace-hack",
]
[[package]]
name = "rustc"
version = "0.0.0"
dependencies = [
"arena",
"backtrace",
"bitflags",
"byteorder",
"jobserver",
"log",
"measureme",
"parking_lot 0.10.0",
"polonius-engine",
"rustc-rayon",
"rustc-rayon-core",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
"scoped-tls",
"serialize",
"smallvec 1.0.0",
]
[[package]]
name = "rustc-ap-arena"
version = "642.0.0"
@ -3603,7 +3570,6 @@ dependencies = [
"libc",
"log",
"measureme",
"rustc",
"rustc-demangle",
"rustc_ast",
"rustc_attr",
@ -3616,6 +3582,7 @@ dependencies = [
"rustc_incremental",
"rustc_index",
"rustc_llvm",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -3634,7 +3601,6 @@ dependencies = [
"log",
"memmap",
"num_cpus",
"rustc",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
@ -3645,6 +3611,7 @@ dependencies = [
"rustc_incremental",
"rustc_index",
"rustc_metadata",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
@ -3685,7 +3652,6 @@ dependencies = [
"env_logger 0.7.1",
"lazy_static 1.4.0",
"log",
"rustc",
"rustc_ast",
"rustc_ast_pretty",
"rustc_codegen_ssa",
@ -3698,6 +3664,7 @@ dependencies = [
"rustc_interface",
"rustc_lint",
"rustc_metadata",
"rustc_middle",
"rustc_mir",
"rustc_parse",
"rustc_plugin_impl",
@ -3797,11 +3764,11 @@ dependencies = [
"graphviz",
"log",
"rand 0.7.3",
"rustc",
"rustc_ast",
"rustc_data_structures",
"rustc_fs_util",
"rustc_hir",
"rustc_middle",
"rustc_session",
"rustc_span",
"serialize",
@ -3821,13 +3788,13 @@ version = "0.0.0"
dependencies = [
"graphviz",
"log",
"rustc",
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -3840,7 +3807,6 @@ version = "0.0.0"
dependencies = [
"log",
"once_cell",
"rustc",
"rustc-rayon",
"rustc_ast",
"rustc_ast_lowering",
@ -3857,6 +3823,7 @@ dependencies = [
"rustc_infer",
"rustc_lint",
"rustc_metadata",
"rustc_middle",
"rustc_mir",
"rustc_mir_build",
"rustc_parse",
@ -3890,7 +3857,6 @@ name = "rustc_lint"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_ast",
"rustc_ast_pretty",
"rustc_attr",
@ -3900,6 +3866,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -3933,7 +3900,6 @@ dependencies = [
"flate2",
"log",
"memmap",
"rustc",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@ -3942,6 +3908,7 @@ dependencies = [
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -3951,6 +3918,39 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "rustc_middle"
version = "0.0.0"
dependencies = [
"arena",
"backtrace",
"bitflags",
"byteorder",
"jobserver",
"log",
"measureme",
"parking_lot 0.10.0",
"polonius-engine",
"rustc-rayon",
"rustc-rayon-core",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_hir",
"rustc_index",
"rustc_macros",
"rustc_query_system",
"rustc_session",
"rustc_span",
"rustc_target",
"scoped-tls",
"serialize",
"smallvec 1.0.0",
]
[[package]]
name = "rustc_mir"
version = "0.0.0"
@ -3961,7 +3961,6 @@ dependencies = [
"log",
"log_settings",
"polonius-engine",
"rustc",
"rustc_apfloat",
"rustc_ast",
"rustc_ast_pretty",
@ -3973,6 +3972,7 @@ dependencies = [
"rustc_infer",
"rustc_lexer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -3987,7 +3987,6 @@ version = "0.0.0"
dependencies = [
"arena",
"log",
"rustc",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
@ -3997,6 +3996,7 @@ dependencies = [
"rustc_index",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4028,7 +4028,6 @@ name = "rustc_passes"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@ -4037,6 +4036,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4047,12 +4047,12 @@ dependencies = [
name = "rustc_plugin_impl"
version = "0.0.0"
dependencies = [
"rustc",
"rustc_ast",
"rustc_errors",
"rustc_hir",
"rustc_lint",
"rustc_metadata",
"rustc_middle",
"rustc_session",
"rustc_span",
]
@ -4062,12 +4062,12 @@ name = "rustc_privacy"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_typeck",
@ -4096,7 +4096,6 @@ dependencies = [
"arena",
"bitflags",
"log",
"rustc",
"rustc_ast",
"rustc_ast_lowering",
"rustc_ast_pretty",
@ -4107,6 +4106,7 @@ dependencies = [
"rustc_feature",
"rustc_hir",
"rustc_metadata",
"rustc_middle",
"rustc_session",
"rustc_span",
"smallvec 1.0.0",
@ -4119,12 +4119,12 @@ dependencies = [
"log",
"rls-data",
"rls-span",
"rustc",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures",
"rustc_hir",
"rustc_hir_pretty",
"rustc_middle",
"rustc_parse",
"rustc_session",
"rustc_span",
@ -4169,12 +4169,12 @@ version = "0.0.0"
dependencies = [
"log",
"punycode",
"rustc",
"rustc-demangle",
"rustc_ast",
"rustc_data_structures",
"rustc_hir",
"rustc_metadata",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4209,7 +4209,6 @@ version = "0.0.0"
dependencies = [
"fmt_macros",
"log",
"rustc",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@ -4218,6 +4217,7 @@ dependencies = [
"rustc_index",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4229,12 +4229,12 @@ name = "rustc_traits"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_ast",
"rustc_data_structures",
"rustc_hir",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
@ -4246,10 +4246,10 @@ name = "rustc_ty"
version = "0.0.0"
dependencies = [
"log",
"rustc",
"rustc_data_structures",
"rustc_hir",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",
@ -4262,7 +4262,6 @@ version = "0.0.0"
dependencies = [
"arena",
"log",
"rustc",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
@ -4270,6 +4269,7 @@ dependencies = [
"rustc_hir",
"rustc_index",
"rustc_infer",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_target",

View File

@ -256,7 +256,7 @@ Also, you may find the [rustdocs for the compiler itself][rustdocs] useful.
[rust-discord]: https://discord.gg/rust-lang
[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/about-this-guide.html
[rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
[rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/
## License

View File

@ -1022,8 +1022,13 @@ impl<'a> Builder<'a> {
cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
}
if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) {
if let Some(map_to) = self.build.debuginfo_map_to(GitRepo::Rustc) {
let map = format!("{}={}", self.build.src.display(), map_to);
cargo.env("RUSTC_DEBUGINFO_MAP", map);
// `rustc` needs to know the virtual `/rustc/$hash` we're mapping to,
// in order to opportunistically reverse it later.
cargo.env("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR", map_to);
}
// Enable usage of unstable features

View File

@ -22,7 +22,7 @@ use serde::Deserialize;
use crate::builder::Cargo;
use crate::dist;
use crate::native;
use crate::util::{exe, is_dylib};
use crate::util::{exe, is_dylib, symlink_dir};
use crate::{Compiler, GitRepo, Mode};
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
@ -633,6 +633,30 @@ impl Step for Sysroot {
};
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
// Symlink the source root into the same location inside the sysroot,
// where `rust-src` component would go (`$sysroot/lib/rustlib/src/rust`),
// so that any tools relying on `rust-src` also work for local builds,
// and also for translating the virtual `/rustc/$hash` back to the real
// directory (for running tests with `rust.remap-debuginfo = true`).
let sysroot_lib_rustlib_src = sysroot.join("lib/rustlib/src");
t!(fs::create_dir_all(&sysroot_lib_rustlib_src));
let sysroot_lib_rustlib_src_rust = sysroot_lib_rustlib_src.join("rust");
if let Err(e) = symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_src_rust) {
eprintln!(
"warning: creating symbolic link `{}` to `{}` failed with {}",
sysroot_lib_rustlib_src_rust.display(),
builder.src.display(),
e,
);
if builder.config.rust_remap_debuginfo {
eprintln!(
"warning: some `src/test/ui` tests will fail when lacking `{}`",
sysroot_lib_rustlib_src_rust.display(),
);
}
}
INTERNER.intern_path(sysroot)
}
}
@ -911,7 +935,11 @@ pub fn stream_cargo(
}
// Instruct Cargo to give us json messages on stdout, critically leaving
// stderr as piped so we can get those pretty colors.
let mut message_format = String::from("json-render-diagnostics");
let mut message_format = if builder.config.json_output {
String::from("json")
} else {
String::from("json-render-diagnostics")
};
if let Some(s) = &builder.config.rustc_error_format {
message_format.push_str(",json-diagnostic-");
message_format.push_str(s);

View File

@ -48,6 +48,7 @@ pub struct Config {
pub ignore_git: bool,
pub exclude: Vec<PathBuf>,
pub rustc_error_format: Option<String>,
pub json_output: bool,
pub test_compare_mode: bool,
pub llvm_libunwind: bool,
@ -415,6 +416,7 @@ impl Config {
let mut config = Config::default_opts();
config.exclude = flags.exclude;
config.rustc_error_format = flags.rustc_error_format;
config.json_output = flags.json_output;
config.on_fail = flags.on_fail;
config.stage = flags.stage;
config.jobs = flags.jobs.map(threads_from_config);

View File

@ -31,6 +31,7 @@ pub struct Flags {
pub incremental: bool,
pub exclude: Vec<PathBuf>,
pub rustc_error_format: Option<String>,
pub json_output: bool,
pub dry_run: bool,
// This overrides the deny-warnings configuration option,
@ -156,6 +157,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
"VALUE",
);
opts.optopt("", "error-format", "rustc error format", "FORMAT");
opts.optflag("", "json-output", "use message-format=json");
opts.optopt(
"",
"llvm-skip-rebuild",
@ -503,6 +505,7 @@ Arguments:
dry_run: matches.opt_present("dry-run"),
on_fail: matches.opt_str("on-fail"),
rustc_error_format: matches.opt_str("error-format"),
json_output: matches.opt_present("json-output"),
keep_stage: matches
.opt_strs("keep-stage")
.into_iter()

View File

@ -740,19 +740,18 @@ impl Build {
self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32)
}
fn debuginfo_map(&self, which: GitRepo) -> Option<String> {
fn debuginfo_map_to(&self, which: GitRepo) -> Option<String> {
if !self.config.rust_remap_debuginfo {
return None;
}
let path = match which {
match which {
GitRepo::Rustc => {
let sha = self.rust_sha().unwrap_or(channel::CFG_RELEASE_NUM);
format!("/rustc/{}", sha)
Some(format!("/rustc/{}", sha))
}
GitRepo::Llvm => String::from("/rustc/llvm"),
};
Some(format!("{}={}", self.src.display(), path))
GitRepo::Llvm => Some(String::from("/rustc/llvm")),
}
}
/// Returns the path to the C compiler for the target specified.
@ -787,7 +786,8 @@ impl Build {
base.push("-fno-omit-frame-pointer".into());
}
if let Some(map) = self.debuginfo_map(which) {
if let Some(map_to) = self.debuginfo_map_to(which) {
let map = format!("{}={}", self.src.display(), map_to);
let cc = self.cc(target);
if cc.ends_with("clang") || cc.ends_with("gcc") {
base.push(format!("-fdebug-prefix-map={}", map));

View File

@ -21,7 +21,7 @@ use crate::flags::Subcommand;
use crate::native;
use crate::tool::{self, SourceType, Tool};
use crate::toolstate::ToolState;
use crate::util::{self, dylib_path, dylib_path_var};
use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var};
use crate::Crate as CargoCrate;
use crate::{envify, DocTests, GitRepo, Mode};
@ -1178,6 +1178,15 @@ impl Step for Compiletest {
cmd.arg("--system-llvm");
}
// Tests that use compiler libraries may inherit the `-lLLVM` link
// requirement, but the `-L` library path is not propagated across
// separate compilations. We can add LLVM's library path to the
// platform-specific environment variable as a workaround.
if !builder.config.dry_run && suite.ends_with("fulldeps") {
let llvm_libdir = output(Command::new(&llvm_config).arg("--libdir"));
add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd);
}
// Only pass correct values for these flags for the `run-make` suite as it
// requires that a C++ compiler was configured which isn't always the case.
if !builder.config.dry_run && suite == "run-make-fulldeps" {

View File

@ -138,15 +138,14 @@ $category > $option = $value -- $comment
For targets: `arm-unknown-linux-gnueabi`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
- Path and misc options > Patches origin = Bundled, then local
- Path and misc options > Local patch directory = /tmp/patches
- Path and misc options > Patches origin = Bundled only
- Target options > Target Architecture = arm
- Target options > Architecture level = armv6 -- (+)
- Target options > Floating point = software (no FPU) -- (\*)
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 3.2.72 -- Precise kernel
- C-library > glibc version = 2.16.0
- C compiler > gcc version = 5.2.0
- Operating System > Linux kernel version = 3.2.101
- C-library > glibc version = 2.17.0
- C compiler > gcc version = 8.3.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
### `arm-linux-gnueabihf.config`
@ -154,17 +153,16 @@ For targets: `arm-unknown-linux-gnueabi`
For targets: `arm-unknown-linux-gnueabihf`
- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
- Path and misc options > Patches origin = Bundled, then local
- Path and misc options > Local patch directory = /tmp/patches
- Path and misc options > Patches origin = Bundled only
- Target options > Target Architecture = arm
- Target options > Architecture level = armv6 -- (+)
- Target options > Use specific FPU = vfp -- (+)
- Target options > Floating point = hardware (FPU) -- (\*)
- Target options > Default instruction set mode = arm -- (+)
- Operating System > Target OS = linux
- Operating System > Linux kernel version = 3.2.72 -- Precise kernel
- C-library > glibc version = 2.16.0
- C compiler > gcc version = 5.2.0
- Operating System > Linux kernel version = 3.2.101
- C-library > glibc version = 2.17.0
- C compiler > gcc version = 8.3.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
### `armv7-linux-gnueabihf.config`

View File

@ -3,20 +3,14 @@ FROM ubuntu:16.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
# Ubuntu 16.04 (this container) ships with make 4, but something in the
# toolchains we build below chokes on that, so go back to make 3
COPY scripts/make3.sh /scripts/
RUN sh /scripts/make3.sh
COPY scripts/crosstool-ng.sh /scripts/
RUN sh /scripts/crosstool-ng.sh
COPY scripts/crosstool-ng-1.24.sh /scripts/
RUN sh /scripts/crosstool-ng-1.24.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
USER rustbuild
WORKDIR /tmp
COPY dist-arm-linux/patches/ /tmp/patches/
COPY dist-arm-linux/arm-linux-gnueabi.config dist-arm-linux/build-toolchains.sh /tmp/
RUN ./build-toolchains.sh

View File

@ -1,9 +1,29 @@
#
# Automatically generated file; DO NOT EDIT.
# Crosstool-NG Configuration
# crosstool-NG Configuration
#
CT_CONFIGURE_has_make381=y
CT_CONFIGURE_has_xz=y
CT_CONFIGURE_has_static_link=y
CT_CONFIGURE_has_cxx11=y
CT_CONFIGURE_has_wget=y
CT_CONFIGURE_has_curl=y
CT_CONFIGURE_has_make_3_81_or_newer=y
CT_CONFIGURE_has_make_4_0_or_newer=y
CT_CONFIGURE_has_libtool_2_4_or_newer=y
CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
CT_CONFIGURE_has_autoconf_2_65_or_newer=y
CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
CT_CONFIGURE_has_automake_1_15_or_newer=y
CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
CT_CONFIGURE_has_bison_2_7_or_newer=y
CT_CONFIGURE_has_python=y
CT_CONFIGURE_has_git=y
CT_CONFIGURE_has_md5sum=y
CT_CONFIGURE_has_sha1sum=y
CT_CONFIGURE_has_sha256sum=y
CT_CONFIGURE_has_sha512sum=y
CT_CONFIGURE_has_install_with_strip_program=y
CT_CONFIG_VERSION_CURRENT="3"
CT_CONFIG_VERSION="3"
CT_MODULES=y
#
@ -20,41 +40,48 @@ CT_MODULES=y
#
# Paths
#
CT_LOCAL_TARBALLS_DIR=""
CT_LOCAL_TARBALLS_DIR="${HOME}/src"
CT_SAVE_TARBALLS=y
# CT_TARBALLS_BUILDROOT_LAYOUT is not set
CT_WORK_DIR="${CT_TOP_DIR}/.build"
CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
CT_RM_RF_PREFIX_DIR=y
CT_REMOVE_DOCS=y
CT_INSTALL_DIR_RO=y
CT_INSTALL_LICENSES=y
CT_PREFIX_DIR_RO=y
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
#
# Downloading
#
CT_DOWNLOAD_AGENT_WGET=y
# CT_DOWNLOAD_AGENT_CURL is not set
# CT_DOWNLOAD_AGENT_NONE is not set
# CT_FORBID_DOWNLOAD is not set
# CT_FORCE_DOWNLOAD is not set
CT_CONNECT_TIMEOUT=10
CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
# CT_ONLY_DOWNLOAD is not set
# CT_USE_MIRROR is not set
CT_VERIFY_DOWNLOAD_DIGEST=y
CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
#
# Extracting
#
# CT_FORCE_EXTRACT is not set
CT_OVERIDE_CONFIG_GUESS_SUB=y
CT_OVERRIDE_CONFIG_GUESS_SUB=y
# CT_ONLY_EXTRACT is not set
# CT_PATCH_BUNDLED is not set
# CT_PATCH_LOCAL is not set
CT_PATCH_BUNDLED_LOCAL=y
# CT_PATCH_LOCAL_BUNDLED is not set
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
# CT_PATCH_NONE is not set
CT_PATCH_ORDER="bundled,local"
CT_PATCH_USE_LOCAL=y
CT_LOCAL_PATCH_DIR="/tmp/patches"
CT_PATCH_BUNDLED=y
# CT_PATCH_BUNDLED_LOCAL is not set
CT_PATCH_ORDER="bundled"
#
# Build behavior
@ -77,11 +104,11 @@ CT_CONFIG_SHELL="${bash}"
#
# CT_LOG_ERROR is not set
# CT_LOG_WARN is not set
CT_LOG_INFO=y
# CT_LOG_EXTRA is not set
# CT_LOG_INFO is not set
CT_LOG_EXTRA=y
# CT_LOG_ALL is not set
# CT_LOG_DEBUG is not set
CT_LOG_LEVEL_MAX="INFO"
CT_LOG_LEVEL_MAX="EXTRA"
# CT_LOG_SEE_TOOLS_WARN is not set
CT_LOG_PROGRESS_BAR=y
CT_LOG_TO_FILE=y
@ -90,84 +117,85 @@ CT_LOG_FILE_COMPRESS=y
#
# Target options
#
# CT_ARCH_ALPHA is not set
# CT_ARCH_ARC is not set
CT_ARCH_ARM=y
# CT_ARCH_AVR is not set
# CT_ARCH_M68K is not set
# CT_ARCH_MIPS is not set
# CT_ARCH_NIOS2 is not set
# CT_ARCH_POWERPC is not set
# CT_ARCH_S390 is not set
# CT_ARCH_SH is not set
# CT_ARCH_SPARC is not set
# CT_ARCH_X86 is not set
# CT_ARCH_XTENSA is not set
CT_ARCH="arm"
CT_ARCH_SUPPORTS_BOTH_MMU=y
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_64=y
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_SUPPORTS_WITH_FLOAT=y
CT_ARCH_SUPPORTS_WITH_FPU=y
CT_ARCH_SUPPORTS_SOFTFP=y
CT_ARCH_DEFAULT_HAS_MMU=y
CT_ARCH_DEFAULT_LE=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_ARCH="armv6"
CT_ARCH_CHOICE_KSYM="ARM"
# CT_ARCH_ALPHA_EV4 is not set
# CT_ARCH_ALPHA_EV45 is not set
# CT_ARCH_ALPHA_EV5 is not set
# CT_ARCH_ALPHA_EV56 is not set
# CT_ARCH_ALPHA_EV6 is not set
# CT_ARCH_ALPHA_EV67 is not set
CT_ARCH_CPU=""
CT_ARCH_TUNE=""
CT_ARCH_FPU=""
# CT_ARCH_BE is not set
CT_ARCH_LE=y
CT_ARCH_32=y
# CT_ARCH_64 is not set
CT_ARCH_BITNESS=32
# CT_ARCH_FLOAT_HW is not set
CT_ARCH_FLOAT_SW=y
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
# CT_ARCH_alpha is not set
CT_ARCH_arm=y
# CT_ARCH_avr is not set
# CT_ARCH_m68k is not set
# CT_ARCH_mips is not set
# CT_ARCH_nios2 is not set
# CT_ARCH_powerpc is not set
# CT_ARCH_s390 is not set
# CT_ARCH_sh is not set
# CT_ARCH_sparc is not set
# CT_ARCH_x86 is not set
# CT_ARCH_xtensa is not set
CT_ARCH_alpha_AVAILABLE=y
CT_ARCH_arm_AVAILABLE=y
CT_ARCH_avr_AVAILABLE=y
CT_ARCH_m68k_AVAILABLE=y
CT_ARCH_microblaze_AVAILABLE=y
CT_ARCH_mips_AVAILABLE=y
CT_ARCH_nios2_AVAILABLE=y
CT_ARCH_powerpc_AVAILABLE=y
CT_ARCH_s390_AVAILABLE=y
CT_ARCH_sh_AVAILABLE=y
CT_ARCH_sparc_AVAILABLE=y
CT_ARCH_x86_AVAILABLE=y
CT_ARCH_xtensa_AVAILABLE=y
CT_ARCH_SUFFIX=""
CT_ARCH_ARM_SHOW=y
#
# Generic target options
#
# CT_MULTILIB is not set
CT_ARCH_USE_MMU=y
CT_ARCH_ENDIAN="little"
#
# Target optimisations
#
CT_ARCH_EXCLUSIVE_WITH_CPU=y
# CT_ARCH_FLOAT_AUTO is not set
# CT_ARCH_FLOAT_SOFTFP is not set
CT_ARCH_FLOAT="soft"
#
# arm other options
# Options for arm
#
CT_ARCH_ARM_PKG_KSYM=""
CT_ARCH_ARM_MODE="arm"
CT_ARCH_ARM_MODE_ARM=y
# CT_ARCH_ARM_MODE_THUMB is not set
# CT_ARCH_ARM_INTERWORKING is not set
CT_ARCH_ARM_EABI_FORCE=y
CT_ARCH_ARM_EABI=y
CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
CT_ARCH_SUFFIX=""
# CT_OMIT_TARGET_VENDOR is not set
#
# Generic target options
#
# CT_MULTILIB is not set
CT_DEMULTILIB=y
CT_ARCH_SUPPORTS_BOTH_MMU=y
CT_ARCH_DEFAULT_HAS_MMU=y
CT_ARCH_USE_MMU=y
CT_ARCH_SUPPORTS_FLAT_FORMAT=y
CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
CT_ARCH_DEFAULT_LE=y
# CT_ARCH_BE is not set
CT_ARCH_LE=y
CT_ARCH_ENDIAN="little"
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_64=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_BITNESS=32
CT_ARCH_32=y
# CT_ARCH_64 is not set
#
# Target optimisations
#
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_SUPPORTS_WITH_FLOAT=y
CT_ARCH_SUPPORTS_WITH_FPU=y
CT_ARCH_SUPPORTS_SOFTFP=y
CT_ARCH_EXCLUSIVE_WITH_CPU=y
CT_ARCH_ARCH="armv6"
CT_ARCH_FPU=""
# CT_ARCH_FLOAT_AUTO is not set
# CT_ARCH_FLOAT_HW is not set
# CT_ARCH_FLOAT_SOFTFP is not set
CT_ARCH_FLOAT_SW=y
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
CT_ARCH_FLOAT="soft"
#
# Toolchain options
@ -181,7 +209,9 @@ CT_USE_SYSROOT=y
CT_SYSROOT_NAME="sysroot"
CT_SYSROOT_DIR_PREFIX=""
CT_WANTS_STATIC_LINK=y
CT_WANTS_STATIC_LINK_CXX=y
# CT_STATIC_TOOLCHAIN is not set
CT_SHOW_CT_VERSION=y
CT_TOOLCHAIN_PKGVERSION=""
CT_TOOLCHAIN_BUGURL=""
@ -215,126 +245,215 @@ CT_BUILD_SUFFIX=""
# Operating System
#
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
# CT_KERNEL_BARE_METAL is not set
CT_KERNEL_LINUX=y
CT_KERNEL="linux"
CT_KERNEL_VERSION="3.2.72"
# CT_KERNEL_bare_metal is not set
CT_KERNEL_linux=y
CT_KERNEL_bare_metal_AVAILABLE=y
CT_KERNEL_linux_AVAILABLE=y
# CT_KERNEL_V_4_3 is not set
# CT_KERNEL_V_4_2 is not set
# CT_KERNEL_V_4_1 is not set
# CT_KERNEL_V_3_18 is not set
# CT_KERNEL_V_3_14 is not set
# CT_KERNEL_V_3_12 is not set
# CT_KERNEL_V_3_10 is not set
# CT_KERNEL_V_3_4 is not set
CT_KERNEL_V_3_2=y
# CT_KERNEL_V_2_6_32 is not set
# CT_KERNEL_LINUX_CUSTOM is not set
CT_KERNEL_windows_AVAILABLE=y
CT_KERNEL_CHOICE_KSYM="LINUX"
CT_KERNEL_LINUX_SHOW=y
#
# Options for linux
#
CT_KERNEL_LINUX_PKG_KSYM="LINUX"
CT_LINUX_DIR_NAME="linux"
CT_LINUX_PKG_NAME="linux"
CT_LINUX_SRC_RELEASE=y
CT_LINUX_PATCH_ORDER="global"
# CT_LINUX_V_4_20 is not set
# CT_LINUX_V_4_19 is not set
# CT_LINUX_V_4_18 is not set
# CT_LINUX_V_4_17 is not set
# CT_LINUX_V_4_16 is not set
# CT_LINUX_V_4_15 is not set
# CT_LINUX_V_4_14 is not set
# CT_LINUX_V_4_13 is not set
# CT_LINUX_V_4_12 is not set
# CT_LINUX_V_4_11 is not set
# CT_LINUX_V_4_10 is not set
# CT_LINUX_V_4_9 is not set
# CT_LINUX_V_4_4 is not set
# CT_LINUX_V_4_1 is not set
# CT_LINUX_V_3_16 is not set
# CT_LINUX_V_3_13 is not set
# CT_LINUX_V_3_12 is not set
# CT_LINUX_V_3_10 is not set
# CT_LINUX_V_3_4 is not set
CT_LINUX_V_3_2=y
# CT_LINUX_V_2_6_32 is not set
# CT_LINUX_NO_VERSIONS is not set
CT_LINUX_VERSION="3.2.101"
CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
CT_LINUX_4_8_or_older=y
CT_LINUX_older_than_4_8=y
CT_LINUX_3_7_or_older=y
CT_LINUX_older_than_3_7=y
CT_LINUX_later_than_3_2=y
CT_LINUX_3_2_or_later=y
CT_KERNEL_LINUX_VERBOSITY_0=y
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
CT_KERNEL_LINUX_INSTALL_CHECK=y
CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
#
# Common kernel options
#
CT_SHARED_LIBS=y
#
# linux other options
#
CT_KERNEL_LINUX_VERBOSITY_0=y
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
CT_KERNEL_LINUX_INSTALL_CHECK=y
#
# Binary utilities
#
CT_ARCH_BINFMT_ELF=y
CT_BINUTILS_BINUTILS=y
CT_BINUTILS="binutils"
CT_BINUTILS_binutils=y
CT_BINUTILS_CHOICE_KSYM="BINUTILS"
CT_BINUTILS_BINUTILS_SHOW=y
#
# Options for binutils
#
CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
CT_BINUTILS_DIR_NAME="binutils"
CT_BINUTILS_USE_GNU=y
CT_BINUTILS_USE="BINUTILS"
CT_BINUTILS_PKG_NAME="binutils"
CT_BINUTILS_SRC_RELEASE=y
CT_BINUTILS_PATCH_ORDER="global"
CT_BINUTILS_V_2_32=y
# CT_BINUTILS_V_2_31 is not set
# CT_BINUTILS_V_2_30 is not set
# CT_BINUTILS_V_2_29 is not set
# CT_BINUTILS_V_2_28 is not set
# CT_BINUTILS_V_2_27 is not set
# CT_BINUTILS_V_2_26 is not set
# CT_BINUTILS_NO_VERSIONS is not set
CT_BINUTILS_VERSION="2.32"
CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
CT_BINUTILS_later_than_2_30=y
CT_BINUTILS_2_30_or_later=y
CT_BINUTILS_later_than_2_27=y
CT_BINUTILS_2_27_or_later=y
CT_BINUTILS_later_than_2_25=y
CT_BINUTILS_2_25_or_later=y
CT_BINUTILS_later_than_2_23=y
CT_BINUTILS_2_23_or_later=y
#
# GNU binutils
#
# CT_CC_BINUTILS_SHOW_LINARO is not set
CT_BINUTILS_V_2_25_1=y
# CT_BINUTILS_V_2_25 is not set
# CT_BINUTILS_V_2_24 is not set
# CT_BINUTILS_V_2_23_2 is not set
# CT_BINUTILS_V_2_23_1 is not set
# CT_BINUTILS_V_2_22 is not set
# CT_BINUTILS_V_2_21_53 is not set
# CT_BINUTILS_V_2_21_1a is not set
# CT_BINUTILS_V_2_20_1a is not set
# CT_BINUTILS_V_2_19_1a is not set
# CT_BINUTILS_V_2_18a is not set
CT_BINUTILS_VERSION="2.25.1"
CT_BINUTILS_2_25_1_or_later=y
CT_BINUTILS_2_25_or_later=y
CT_BINUTILS_2_24_or_later=y
CT_BINUTILS_2_23_or_later=y
CT_BINUTILS_2_22_or_later=y
CT_BINUTILS_2_21_or_later=y
CT_BINUTILS_2_20_or_later=y
CT_BINUTILS_2_19_or_later=y
CT_BINUTILS_2_18_or_later=y
CT_BINUTILS_HAS_HASH_STYLE=y
CT_BINUTILS_HAS_GOLD=y
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_GOLD_SUPPORT=y
CT_BINUTILS_HAS_PLUGINS=y
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
CT_BINUTILS_FORCE_LD_BFD=y
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_GOLD_SUPPORT=y
CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
CT_BINUTILS_LINKER_LD=y
# CT_BINUTILS_LINKER_LD_GOLD is not set
# CT_BINUTILS_LINKER_GOLD_LD is not set
CT_BINUTILS_LINKERS_LIST="ld"
CT_BINUTILS_LINKER_DEFAULT="bfd"
# CT_BINUTILS_PLUGINS is not set
CT_BINUTILS_RELRO=m
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
# CT_BINUTILS_FOR_TARGET is not set
#
# binutils other options
#
CT_ALL_BINUTILS_CHOICES="BINUTILS"
#
# C-library
#
CT_LIBC_GLIBC=y
# CT_LIBC_NEWLIB is not set
# CT_LIBC_NONE is not set
# CT_LIBC_UCLIBC is not set
CT_LIBC="glibc"
CT_LIBC_VERSION="2.16.0"
CT_LIBC_glibc=y
# CT_LIBC_musl is not set
# CT_LIBC_uClibc is not set
CT_LIBC_avr_libc_AVAILABLE=y
CT_LIBC_glibc_AVAILABLE=y
CT_LIBC_CHOICE_KSYM="GLIBC"
CT_THREADS="nptl"
# CT_CC_GLIBC_SHOW_LINARO is not set
# CT_LIBC_GLIBC_V_2_22 is not set
# CT_LIBC_GLIBC_V_2_21 is not set
# CT_LIBC_GLIBC_V_2_20 is not set
# CT_LIBC_GLIBC_V_2_19 is not set
# CT_LIBC_GLIBC_V_2_18 is not set
# CT_LIBC_GLIBC_V_2_17 is not set
CT_LIBC_GLIBC_V_2_16_0=y
# CT_LIBC_GLIBC_V_2_15 is not set
# CT_LIBC_GLIBC_V_2_14_1 is not set
# CT_LIBC_GLIBC_V_2_14 is not set
# CT_LIBC_GLIBC_V_2_13 is not set
# CT_LIBC_GLIBC_V_2_12_2 is not set
# CT_LIBC_GLIBC_V_2_12_1 is not set
# CT_LIBC_GLIBC_V_2_11_1 is not set
# CT_LIBC_GLIBC_V_2_11 is not set
# CT_LIBC_GLIBC_V_2_10_1 is not set
# CT_LIBC_GLIBC_V_2_9 is not set
# CT_LIBC_GLIBC_V_2_8 is not set
CT_LIBC_mingw_AVAILABLE=y
CT_LIBC_musl_AVAILABLE=y
CT_LIBC_newlib_AVAILABLE=y
CT_LIBC_none_AVAILABLE=y
CT_LIBC_uClibc_AVAILABLE=y
CT_LIBC_GLIBC_SHOW=y
#
# Options for glibc
#
CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
CT_GLIBC_DIR_NAME="glibc"
CT_GLIBC_USE_GNU=y
CT_GLIBC_USE="GLIBC"
CT_GLIBC_PKG_NAME="glibc"
CT_GLIBC_SRC_RELEASE=y
CT_GLIBC_PATCH_ORDER="global"
# CT_GLIBC_V_2_28 is not set
# CT_GLIBC_V_2_27 is not set
# CT_GLIBC_V_2_26 is not set
# CT_GLIBC_V_2_25 is not set
# CT_GLIBC_V_2_24 is not set
# CT_GLIBC_V_2_23 is not set
# CT_GLIBC_V_2_19 is not set
CT_GLIBC_V_2_17=y
# CT_GLIBC_V_2_12_1 is not set
# CT_GLIBC_NO_VERSIONS is not set
CT_GLIBC_VERSION="2.17"
CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
CT_GLIBC_2_29_or_older=y
CT_GLIBC_older_than_2_29=y
CT_GLIBC_REQUIRE_older_than_2_29=y
CT_GLIBC_2_27_or_older=y
CT_GLIBC_older_than_2_27=y
CT_GLIBC_2_26_or_older=y
CT_GLIBC_older_than_2_26=y
CT_GLIBC_2_25_or_older=y
CT_GLIBC_older_than_2_25=y
CT_GLIBC_2_24_or_older=y
CT_GLIBC_older_than_2_24=y
CT_GLIBC_2_23_or_older=y
CT_GLIBC_older_than_2_23=y
CT_GLIBC_2_20_or_older=y
CT_GLIBC_older_than_2_20=y
CT_GLIBC_2_17_or_later=y
CT_GLIBC_2_17_or_older=y
CT_GLIBC_later_than_2_14=y
CT_GLIBC_2_14_or_later=y
CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
CT_GLIBC_DEP_BINUTILS=y
CT_GLIBC_DEP_GCC=y
CT_GLIBC_DEP_PYTHON=y
CT_GLIBC_HAS_NPTL_ADDON=y
CT_GLIBC_HAS_PORTS_ADDON=y
CT_GLIBC_HAS_LIBIDN_ADDON=y
CT_GLIBC_USE_PORTS_ADDON=y
CT_GLIBC_USE_NPTL_ADDON=y
# CT_GLIBC_USE_LIBIDN_ADDON is not set
CT_GLIBC_HAS_OBSOLETE_RPC=y
CT_GLIBC_EXTRA_CONFIG_ARRAY=""
CT_GLIBC_CONFIGPARMS=""
CT_GLIBC_EXTRA_CFLAGS=""
CT_GLIBC_ENABLE_OBSOLETE_RPC=y
# CT_GLIBC_DISABLE_VERSIONING is not set
CT_GLIBC_OLDEST_ABI=""
CT_GLIBC_FORCE_UNWIND=y
# CT_GLIBC_LOCALES is not set
# CT_GLIBC_KERNEL_VERSION_NONE is not set
CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
CT_GLIBC_MIN_KERNEL="3.2.101"
# CT_GLIBC_SSP_DEFAULT is not set
# CT_GLIBC_SSP_NO is not set
# CT_GLIBC_SSP_YES is not set
# CT_GLIBC_SSP_ALL is not set
# CT_GLIBC_SSP_STRONG is not set
# CT_NEWLIB_USE_REDHAT is not set
CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
CT_LIBC_SUPPORT_THREADS_ANY=y
CT_LIBC_SUPPORT_THREADS_NATIVE=y
@ -342,100 +461,71 @@ CT_LIBC_SUPPORT_THREADS_NATIVE=y
# Common C library options
#
CT_THREADS_NATIVE=y
# CT_CREATE_LDSO_CONF is not set
CT_LIBC_XLDD=y
#
# glibc other options
#
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
CT_LIBC_glibc_familly=y
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
CT_LIBC_GLIBC_CONFIGPARMS=""
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
CT_LIBC_EXTRA_CC_ARGS=""
# CT_LIBC_DISABLE_VERSIONING is not set
CT_LIBC_OLDEST_ABI=""
CT_LIBC_GLIBC_FORCE_UNWIND=y
CT_LIBC_GLIBC_USE_PORTS=y
CT_LIBC_ADDONS_LIST=""
#
# WARNING !!!
#
#
# For glibc >= 2.8, it can happen that the tarballs
#
#
# for the addons are not available for download.
#
#
# If that happens, bad luck... Try a previous version
#
#
# or try again later... :-(
#
# CT_LIBC_LOCALES is not set
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
CT_LIBC_GLIBC_MIN_KERNEL="3.2.72"
#
# C compiler
#
CT_CC="gcc"
CT_CC_CORE_PASSES_NEEDED=y
CT_CC_CORE_PASS_1_NEEDED=y
CT_CC_CORE_PASS_2_NEEDED=y
CT_CC_gcc=y
# CT_CC_GCC_SHOW_LINARO is not set
CT_CC_GCC_V_5_2_0=y
# CT_CC_GCC_V_4_9_3 is not set
# CT_CC_GCC_V_4_8_5 is not set
# CT_CC_GCC_V_4_7_4 is not set
# CT_CC_GCC_V_4_6_4 is not set
# CT_CC_GCC_V_4_5_4 is not set
# CT_CC_GCC_V_4_4_7 is not set
# CT_CC_GCC_V_4_3_6 is not set
# CT_CC_GCC_V_4_2_4 is not set
CT_CC_GCC_4_2_or_later=y
CT_CC_GCC_4_3_or_later=y
CT_CC_GCC_4_4_or_later=y
CT_CC_GCC_4_5_or_later=y
CT_CC_GCC_4_6_or_later=y
CT_CC_GCC_4_7_or_later=y
CT_CC_GCC_4_8_or_later=y
CT_CC_GCC_4_9_or_later=y
CT_CC_GCC_5=y
CT_CC_GCC_5_or_later=y
CT_CC_GCC_HAS_GRAPHITE=y
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_HAS_LTO=y
CT_CC_GCC_USE_LTO=y
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
CT_CC_GCC_HAS_BUILD_ID=y
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
CT_CC_GCC_USE_GMP_MPFR=y
CT_CC_GCC_USE_MPC=y
CT_CC_GCC_HAS_LIBQUADMATH=y
CT_CC_GCC_HAS_LIBSANITIZER=y
CT_CC_GCC_VERSION="5.2.0"
# CT_CC_LANG_FORTRAN is not set
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_SUPPORT_GOLANG=y
CT_CC_GCC=y
CT_CC="gcc"
CT_CC_CHOICE_KSYM="GCC"
CT_CC_GCC_SHOW=y
#
# Options for gcc
#
CT_CC_GCC_PKG_KSYM="GCC"
CT_GCC_DIR_NAME="gcc"
CT_GCC_USE_GNU=y
CT_GCC_USE="GCC"
CT_GCC_PKG_NAME="gcc"
CT_GCC_SRC_RELEASE=y
CT_GCC_PATCH_ORDER="global"
CT_GCC_V_8=y
# CT_GCC_V_7 is not set
# CT_GCC_V_6 is not set
# CT_GCC_V_5 is not set
# CT_GCC_V_4_9 is not set
# CT_GCC_NO_VERSIONS is not set
CT_GCC_VERSION="8.3.0"
CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_GCC_SIGNATURE_FORMAT=""
CT_GCC_later_than_7=y
CT_GCC_7_or_later=y
CT_GCC_later_than_6=y
CT_GCC_6_or_later=y
CT_GCC_later_than_5=y
CT_GCC_5_or_later=y
CT_GCC_later_than_4_9=y
CT_GCC_4_9_or_later=y
CT_GCC_later_than_4_8=y
CT_GCC_4_8_or_later=y
CT_CC_GCC_HAS_LIBMPX=y
CT_CC_GCC_ENABLE_CXX_FLAGS=""
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_EXTRA_ENV_ARRAY=""
CT_CC_GCC_STATIC_LIBSTDCXX=y
# CT_CC_GCC_SYSTEM_ZLIB is not set
CT_CC_GCC_CONFIG_TLS=m
#
# Optimisation features
#
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_USE_LTO=y
#
# Settings for libraries running on target
@ -464,97 +554,208 @@ CT_CC_GCC_DEC_FLOAT_AUTO=y
# CT_CC_GCC_DEC_FLOAT_BID is not set
# CT_CC_GCC_DEC_FLOAT_DPD is not set
# CT_CC_GCC_DEC_FLOATS_NO is not set
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_JAVA=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_SUPPORT_GOLANG=y
CT_ALL_CC_CHOICES="GCC"
#
# Additional supported languages:
#
CT_CC_LANG_CXX=y
# CT_CC_LANG_JAVA is not set
# CT_CC_LANG_FORTRAN is not set
#
# Debug facilities
#
# CT_DEBUG_dmalloc is not set
# CT_DEBUG_duma is not set
# CT_DEBUG_gdb is not set
# CT_DEBUG_ltrace is not set
# CT_DEBUG_strace is not set
# CT_DEBUG_DUMA is not set
# CT_DEBUG_GDB is not set
# CT_DEBUG_LTRACE is not set
# CT_DEBUG_STRACE is not set
CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
#
# Companion libraries
#
CT_COMPLIBS_NEEDED=y
# CT_COMPLIBS_CHECK is not set
# CT_COMP_LIBS_CLOOG is not set
# CT_COMP_LIBS_EXPAT is not set
CT_COMP_LIBS_GETTEXT=y
CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
CT_GETTEXT_DIR_NAME="gettext"
CT_GETTEXT_PKG_NAME="gettext"
CT_GETTEXT_SRC_RELEASE=y
CT_GETTEXT_PATCH_ORDER="global"
CT_GETTEXT_V_0_19_8_1=y
# CT_GETTEXT_NO_VERSIONS is not set
CT_GETTEXT_VERSION="0.19.8.1"
CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
CT_COMP_LIBS_GMP=y
CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
CT_GMP_DIR_NAME="gmp"
CT_GMP_PKG_NAME="gmp"
CT_GMP_SRC_RELEASE=y
CT_GMP_PATCH_ORDER="global"
CT_GMP_V_6_1=y
# CT_GMP_NO_VERSIONS is not set
CT_GMP_VERSION="6.1.2"
CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
CT_GMP_SIGNATURE_FORMAT="packed/.sig"
CT_GMP_later_than_5_1_0=y
CT_GMP_5_1_0_or_later=y
CT_GMP_later_than_5_0_0=y
CT_GMP_5_0_0_or_later=y
CT_GMP_REQUIRE_5_0_0_or_later=y
CT_COMP_LIBS_ISL=y
CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
CT_ISL_DIR_NAME="isl"
CT_ISL_PKG_NAME="isl"
CT_ISL_SRC_RELEASE=y
CT_ISL_PATCH_ORDER="global"
CT_ISL_V_0_20=y
# CT_ISL_V_0_19 is not set
# CT_ISL_V_0_18 is not set
# CT_ISL_V_0_17 is not set
# CT_ISL_V_0_16 is not set
# CT_ISL_V_0_15 is not set
# CT_ISL_NO_VERSIONS is not set
CT_ISL_VERSION="0.20"
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_ISL_SIGNATURE_FORMAT=""
CT_ISL_later_than_0_18=y
CT_ISL_0_18_or_later=y
CT_ISL_later_than_0_15=y
CT_ISL_0_15_or_later=y
CT_ISL_REQUIRE_0_15_or_later=y
CT_ISL_later_than_0_14=y
CT_ISL_0_14_or_later=y
CT_ISL_REQUIRE_0_14_or_later=y
CT_ISL_later_than_0_13=y
CT_ISL_0_13_or_later=y
CT_ISL_later_than_0_12=y
CT_ISL_0_12_or_later=y
CT_ISL_REQUIRE_0_12_or_later=y
# CT_COMP_LIBS_LIBELF is not set
CT_COMP_LIBS_LIBICONV=y
CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
CT_LIBICONV_DIR_NAME="libiconv"
CT_LIBICONV_PKG_NAME="libiconv"
CT_LIBICONV_SRC_RELEASE=y
CT_LIBICONV_PATCH_ORDER="global"
CT_LIBICONV_V_1_15=y
# CT_LIBICONV_NO_VERSIONS is not set
CT_LIBICONV_VERSION="1.15"
CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
CT_COMP_LIBS_MPC=y
CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
CT_MPC_DIR_NAME="mpc"
CT_MPC_PKG_NAME="mpc"
CT_MPC_SRC_RELEASE=y
CT_MPC_PATCH_ORDER="global"
CT_MPC_V_1_1=y
# CT_MPC_V_1_0 is not set
# CT_MPC_NO_VERSIONS is not set
CT_MPC_VERSION="1.1.0"
CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_FORMATS=".tar.gz"
CT_MPC_SIGNATURE_FORMAT="packed/.sig"
CT_MPC_1_1_0_or_later=y
CT_MPC_1_1_0_or_older=y
CT_COMP_LIBS_MPFR=y
CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
CT_MPFR_DIR_NAME="mpfr"
CT_MPFR_PKG_NAME="mpfr"
CT_MPFR_SRC_RELEASE=y
CT_MPFR_PATCH_ORDER="global"
CT_MPFR_V_4_0=y
# CT_MPFR_V_3_1 is not set
# CT_MPFR_NO_VERSIONS is not set
CT_MPFR_VERSION="4.0.2"
CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
CT_MPFR_later_than_4_0_0=y
CT_MPFR_4_0_0_or_later=y
CT_MPFR_later_than_3_0_0=y
CT_MPFR_3_0_0_or_later=y
CT_MPFR_REQUIRE_3_0_0_or_later=y
CT_COMP_LIBS_NCURSES=y
CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
CT_NCURSES_DIR_NAME="ncurses"
CT_NCURSES_PKG_NAME="ncurses"
CT_NCURSES_SRC_RELEASE=y
CT_NCURSES_PATCH_ORDER="global"
CT_NCURSES_V_6_1=y
# CT_NCURSES_V_6_0 is not set
# CT_NCURSES_NO_VERSIONS is not set
CT_NCURSES_VERSION="6.1"
CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
CT_NCURSES_HOST_CONFIG_ARGS=""
CT_NCURSES_HOST_DISABLE_DB=y
CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
CT_NCURSES_TARGET_CONFIG_ARGS=""
# CT_NCURSES_TARGET_DISABLE_DB is not set
CT_NCURSES_TARGET_FALLBACKS=""
CT_COMP_LIBS_ZLIB=y
CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
CT_ZLIB_DIR_NAME="zlib"
CT_ZLIB_PKG_NAME="zlib"
CT_ZLIB_SRC_RELEASE=y
CT_ZLIB_PATCH_ORDER="global"
CT_ZLIB_V_1_2_11=y
# CT_ZLIB_NO_VERSIONS is not set
CT_ZLIB_VERSION="1.2.11"
CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
CT_LIBICONV_NEEDED=y
CT_GETTEXT_NEEDED=y
CT_GMP_NEEDED=y
CT_MPFR_NEEDED=y
CT_ISL_NEEDED=y
CT_MPC_NEEDED=y
CT_COMPLIBS=y
CT_NCURSES_NEEDED=y
CT_ZLIB_NEEDED=y
CT_LIBICONV=y
CT_GETTEXT=y
CT_GMP=y
CT_MPFR=y
CT_ISL=y
CT_MPC=y
CT_LIBICONV_V_1_14=y
CT_LIBICONV_VERSION="1.14"
CT_GETTEXT_V_0_19_6=y
CT_GETTEXT_VERSION="0.19.6"
CT_GMP_V_6_0_0=y
# CT_GMP_V_5_1_3 is not set
# CT_GMP_V_5_1_1 is not set
# CT_GMP_V_5_0_2 is not set
# CT_GMP_V_5_0_1 is not set
# CT_GMP_V_4_3_2 is not set
# CT_GMP_V_4_3_1 is not set
# CT_GMP_V_4_3_0 is not set
CT_GMP_5_0_2_or_later=y
CT_GMP_VERSION="6.0.0a"
CT_MPFR_V_3_1_3=y
# CT_MPFR_V_3_1_2 is not set
# CT_MPFR_V_3_1_0 is not set
# CT_MPFR_V_3_0_1 is not set
# CT_MPFR_V_3_0_0 is not set
# CT_MPFR_V_2_4_2 is not set
# CT_MPFR_V_2_4_1 is not set
# CT_MPFR_V_2_4_0 is not set
CT_MPFR_VERSION="3.1.3"
CT_ISL_V_0_14=y
# CT_ISL_V_0_12_2 is not set
CT_ISL_V_0_14_or_later=y
CT_ISL_V_0_12_or_later=y
CT_ISL_VERSION="0.14"
# CT_CLOOG_V_0_18_4 is not set
# CT_CLOOG_V_0_18_1 is not set
# CT_CLOOG_V_0_18_0 is not set
CT_MPC_V_1_0_3=y
# CT_MPC_V_1_0_2 is not set
# CT_MPC_V_1_0_1 is not set
# CT_MPC_V_1_0 is not set
# CT_MPC_V_0_9 is not set
# CT_MPC_V_0_8_2 is not set
# CT_MPC_V_0_8_1 is not set
# CT_MPC_V_0_7 is not set
CT_MPC_VERSION="1.0.3"
#
# Companion libraries common options
#
# CT_COMPLIBS_CHECK is not set
CT_NCURSES=y
CT_ZLIB=y
#
# Companion tools
#
#
# READ HELP before you say 'Y' below !!!
#
# CT_COMP_TOOLS is not set
# CT_COMP_TOOLS_FOR_HOST is not set
# CT_COMP_TOOLS_AUTOCONF is not set
# CT_COMP_TOOLS_AUTOMAKE is not set
# CT_COMP_TOOLS_BISON is not set
# CT_COMP_TOOLS_DTC is not set
# CT_COMP_TOOLS_LIBTOOL is not set
# CT_COMP_TOOLS_M4 is not set
# CT_COMP_TOOLS_MAKE is not set
CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"

View File

@ -1,48 +0,0 @@
commit bdb24c2851fd5f0ad9b82d7ea1db911d334b02d2
Author: Joseph Myers <joseph@codesourcery.com>
Date: Tue May 20 21:27:13 2014 +0000
Fix ARM build with GCC trunk.
sysdeps/unix/sysv/linux/arm/unwind-resume.c and
sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c have static
variables that are written in C code but only read from toplevel asms.
Current GCC trunk now optimizes away such apparently write-only static
variables, so causing a build failure. This patch marks those
variables with __attribute_used__ to avoid that optimization.
Tested that this fixes the build for ARM.
* sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c
(libgcc_s_resume): Use __attribute_used__.
* sysdeps/unix/sysv/linux/arm/unwind-resume.c (libgcc_s_resume):
Likewise.
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
index 29e2c2b00b04..e848bfeffdcb 100644
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
@@ -22,7 +22,8 @@
#include <pthreadP.h>
static void *libgcc_s_handle;
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
+ __attribute_used__;
static _Unwind_Reason_Code (*libgcc_s_personality)
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
index 285b99b5ed0d..48d00fc83641 100644
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
@@ -20,7 +20,8 @@
#include <stdio.h>
#include <unwind.h>
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
+ __attribute_used__;
static _Unwind_Reason_Code (*libgcc_s_personality)
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);

View File

@ -3,20 +3,14 @@ FROM ubuntu:16.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
# Ubuntu 16.04 (this container) ships with make 4, but something in the
# toolchains we build below chokes on that, so go back to make 3
COPY scripts/make3.sh /scripts/
RUN sh /scripts/make3.sh
COPY scripts/crosstool-ng.sh /scripts/
RUN sh /scripts/crosstool-ng.sh
COPY scripts/crosstool-ng-1.24.sh /scripts/
RUN sh /scripts/crosstool-ng-1.24.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh
USER rustbuild
WORKDIR /tmp
COPY dist-armhf-linux/patches/ /tmp/patches/
COPY dist-armhf-linux/arm-linux-gnueabihf.config dist-armhf-linux/build-toolchains.sh /tmp/
RUN ./build-toolchains.sh

View File

@ -1,9 +1,29 @@
#
# Automatically generated file; DO NOT EDIT.
# Crosstool-NG Configuration
# crosstool-NG Configuration
#
CT_CONFIGURE_has_make381=y
CT_CONFIGURE_has_xz=y
CT_CONFIGURE_has_static_link=y
CT_CONFIGURE_has_cxx11=y
CT_CONFIGURE_has_wget=y
CT_CONFIGURE_has_curl=y
CT_CONFIGURE_has_make_3_81_or_newer=y
CT_CONFIGURE_has_make_4_0_or_newer=y
CT_CONFIGURE_has_libtool_2_4_or_newer=y
CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
CT_CONFIGURE_has_autoconf_2_65_or_newer=y
CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
CT_CONFIGURE_has_automake_1_15_or_newer=y
CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
CT_CONFIGURE_has_bison_2_7_or_newer=y
CT_CONFIGURE_has_python=y
CT_CONFIGURE_has_git=y
CT_CONFIGURE_has_md5sum=y
CT_CONFIGURE_has_sha1sum=y
CT_CONFIGURE_has_sha256sum=y
CT_CONFIGURE_has_sha512sum=y
CT_CONFIGURE_has_install_with_strip_program=y
CT_CONFIG_VERSION_CURRENT="3"
CT_CONFIG_VERSION="3"
CT_MODULES=y
#
@ -20,41 +40,48 @@ CT_MODULES=y
#
# Paths
#
CT_LOCAL_TARBALLS_DIR=""
CT_LOCAL_TARBALLS_DIR="${HOME}/src"
CT_SAVE_TARBALLS=y
# CT_TARBALLS_BUILDROOT_LAYOUT is not set
CT_WORK_DIR="${CT_TOP_DIR}/.build"
CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
CT_INSTALL_DIR="${CT_PREFIX_DIR}"
CT_RM_RF_PREFIX_DIR=y
CT_REMOVE_DOCS=y
CT_INSTALL_DIR_RO=y
CT_INSTALL_LICENSES=y
CT_PREFIX_DIR_RO=y
CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
#
# Downloading
#
CT_DOWNLOAD_AGENT_WGET=y
# CT_DOWNLOAD_AGENT_CURL is not set
# CT_DOWNLOAD_AGENT_NONE is not set
# CT_FORBID_DOWNLOAD is not set
# CT_FORCE_DOWNLOAD is not set
CT_CONNECT_TIMEOUT=10
CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
# CT_ONLY_DOWNLOAD is not set
# CT_USE_MIRROR is not set
CT_VERIFY_DOWNLOAD_DIGEST=y
CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
#
# Extracting
#
# CT_FORCE_EXTRACT is not set
CT_OVERIDE_CONFIG_GUESS_SUB=y
CT_OVERRIDE_CONFIG_GUESS_SUB=y
# CT_ONLY_EXTRACT is not set
# CT_PATCH_BUNDLED is not set
# CT_PATCH_LOCAL is not set
CT_PATCH_BUNDLED_LOCAL=y
# CT_PATCH_LOCAL_BUNDLED is not set
# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set
# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set
# CT_PATCH_NONE is not set
CT_PATCH_ORDER="bundled,local"
CT_PATCH_USE_LOCAL=y
CT_LOCAL_PATCH_DIR="/tmp/patches"
CT_PATCH_BUNDLED=y
# CT_PATCH_BUNDLED_LOCAL is not set
CT_PATCH_ORDER="bundled"
#
# Build behavior
@ -77,11 +104,11 @@ CT_CONFIG_SHELL="${bash}"
#
# CT_LOG_ERROR is not set
# CT_LOG_WARN is not set
CT_LOG_INFO=y
# CT_LOG_EXTRA is not set
# CT_LOG_INFO is not set
CT_LOG_EXTRA=y
# CT_LOG_ALL is not set
# CT_LOG_DEBUG is not set
CT_LOG_LEVEL_MAX="INFO"
CT_LOG_LEVEL_MAX="EXTRA"
# CT_LOG_SEE_TOOLS_WARN is not set
CT_LOG_PROGRESS_BAR=y
CT_LOG_TO_FILE=y
@ -90,78 +117,35 @@ CT_LOG_FILE_COMPRESS=y
#
# Target options
#
# CT_ARCH_ALPHA is not set
# CT_ARCH_ARC is not set
CT_ARCH_ARM=y
# CT_ARCH_AVR is not set
# CT_ARCH_M68K is not set
# CT_ARCH_MIPS is not set
# CT_ARCH_NIOS2 is not set
# CT_ARCH_POWERPC is not set
# CT_ARCH_S390 is not set
# CT_ARCH_SH is not set
# CT_ARCH_SPARC is not set
# CT_ARCH_X86 is not set
# CT_ARCH_XTENSA is not set
CT_ARCH="arm"
CT_ARCH_SUPPORTS_BOTH_MMU=y
CT_ARCH_SUPPORTS_BOTH_ENDIAN=y
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_64=y
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_SUPPORTS_WITH_FLOAT=y
CT_ARCH_SUPPORTS_WITH_FPU=y
CT_ARCH_SUPPORTS_SOFTFP=y
CT_ARCH_DEFAULT_HAS_MMU=y
CT_ARCH_DEFAULT_LE=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_ARCH="armv6"
CT_ARCH_CHOICE_KSYM="ARM"
# CT_ARCH_ALPHA_EV4 is not set
# CT_ARCH_ALPHA_EV45 is not set
# CT_ARCH_ALPHA_EV5 is not set
# CT_ARCH_ALPHA_EV56 is not set
# CT_ARCH_ALPHA_EV6 is not set
# CT_ARCH_ALPHA_EV67 is not set
CT_ARCH_CPU=""
CT_ARCH_TUNE=""
CT_ARCH_FPU="vfp"
# CT_ARCH_BE is not set
CT_ARCH_LE=y
CT_ARCH_32=y
# CT_ARCH_64 is not set
CT_ARCH_BITNESS=32
CT_ARCH_FLOAT_HW=y
# CT_ARCH_FLOAT_SW is not set
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
# CT_ARCH_alpha is not set
CT_ARCH_arm=y
# CT_ARCH_avr is not set
# CT_ARCH_m68k is not set
# CT_ARCH_mips is not set
# CT_ARCH_nios2 is not set
# CT_ARCH_powerpc is not set
# CT_ARCH_s390 is not set
# CT_ARCH_sh is not set
# CT_ARCH_sparc is not set
# CT_ARCH_x86 is not set
# CT_ARCH_xtensa is not set
CT_ARCH_alpha_AVAILABLE=y
CT_ARCH_arm_AVAILABLE=y
CT_ARCH_avr_AVAILABLE=y
CT_ARCH_m68k_AVAILABLE=y
CT_ARCH_microblaze_AVAILABLE=y
CT_ARCH_mips_AVAILABLE=y
CT_ARCH_nios2_AVAILABLE=y
CT_ARCH_powerpc_AVAILABLE=y
CT_ARCH_s390_AVAILABLE=y
CT_ARCH_sh_AVAILABLE=y
CT_ARCH_sparc_AVAILABLE=y
CT_ARCH_x86_AVAILABLE=y
CT_ARCH_xtensa_AVAILABLE=y
CT_ARCH_SUFFIX=""
CT_ARCH_ARM_SHOW=y
#
# Generic target options
#
# CT_MULTILIB is not set
CT_ARCH_USE_MMU=y
CT_ARCH_ENDIAN="little"
#
# Target optimisations
#
CT_ARCH_EXCLUSIVE_WITH_CPU=y
# CT_ARCH_FLOAT_AUTO is not set
# CT_ARCH_FLOAT_SOFTFP is not set
CT_ARCH_FLOAT="hard"
#
# arm other options
# Options for arm
#
CT_ARCH_ARM_PKG_KSYM=""
CT_ARCH_ARM_MODE="arm"
CT_ARCH_ARM_MODE_ARM=y
# CT_ARCH_ARM_MODE_THUMB is not set
@ -169,6 +153,50 @@ CT_ARCH_ARM_MODE_ARM=y
CT_ARCH_ARM_EABI_FORCE=y
CT_ARCH_ARM_EABI=y
CT_ARCH_ARM_TUPLE_USE_EABIHF=y
CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
CT_ARCH_SUFFIX=""
# CT_OMIT_TARGET_VENDOR is not set
#
# Generic target options
#
# CT_MULTILIB is not set
CT_DEMULTILIB=y
CT_ARCH_SUPPORTS_BOTH_MMU=y
CT_ARCH_DEFAULT_HAS_MMU=y
CT_ARCH_USE_MMU=y
CT_ARCH_SUPPORTS_FLAT_FORMAT=y
CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
CT_ARCH_DEFAULT_LE=y
# CT_ARCH_BE is not set
CT_ARCH_LE=y
CT_ARCH_ENDIAN="little"
CT_ARCH_SUPPORTS_32=y
CT_ARCH_SUPPORTS_64=y
CT_ARCH_DEFAULT_32=y
CT_ARCH_BITNESS=32
CT_ARCH_32=y
# CT_ARCH_64 is not set
#
# Target optimisations
#
CT_ARCH_SUPPORTS_WITH_ARCH=y
CT_ARCH_SUPPORTS_WITH_CPU=y
CT_ARCH_SUPPORTS_WITH_TUNE=y
CT_ARCH_SUPPORTS_WITH_FLOAT=y
CT_ARCH_SUPPORTS_WITH_FPU=y
CT_ARCH_SUPPORTS_SOFTFP=y
CT_ARCH_EXCLUSIVE_WITH_CPU=y
CT_ARCH_ARCH="armv6"
CT_ARCH_FPU="vfp"
# CT_ARCH_FLOAT_AUTO is not set
CT_ARCH_FLOAT_HW=y
# CT_ARCH_FLOAT_SOFTFP is not set
# CT_ARCH_FLOAT_SW is not set
CT_TARGET_CFLAGS=""
CT_TARGET_LDFLAGS=""
CT_ARCH_FLOAT="hard"
#
# Toolchain options
@ -182,7 +210,9 @@ CT_USE_SYSROOT=y
CT_SYSROOT_NAME="sysroot"
CT_SYSROOT_DIR_PREFIX=""
CT_WANTS_STATIC_LINK=y
CT_WANTS_STATIC_LINK_CXX=y
# CT_STATIC_TOOLCHAIN is not set
CT_SHOW_CT_VERSION=y
CT_TOOLCHAIN_PKGVERSION=""
CT_TOOLCHAIN_BUGURL=""
@ -216,126 +246,215 @@ CT_BUILD_SUFFIX=""
# Operating System
#
CT_KERNEL_SUPPORTS_SHARED_LIBS=y
# CT_KERNEL_BARE_METAL is not set
CT_KERNEL_LINUX=y
CT_KERNEL="linux"
CT_KERNEL_VERSION="3.2.72"
# CT_KERNEL_bare_metal is not set
CT_KERNEL_linux=y
CT_KERNEL_bare_metal_AVAILABLE=y
CT_KERNEL_linux_AVAILABLE=y
# CT_KERNEL_V_4_3 is not set
# CT_KERNEL_V_4_2 is not set
# CT_KERNEL_V_4_1 is not set
# CT_KERNEL_V_3_18 is not set
# CT_KERNEL_V_3_14 is not set
# CT_KERNEL_V_3_12 is not set
# CT_KERNEL_V_3_10 is not set
# CT_KERNEL_V_3_4 is not set
CT_KERNEL_V_3_2=y
# CT_KERNEL_V_2_6_32 is not set
# CT_KERNEL_LINUX_CUSTOM is not set
CT_KERNEL_windows_AVAILABLE=y
CT_KERNEL_CHOICE_KSYM="LINUX"
CT_KERNEL_LINUX_SHOW=y
#
# Options for linux
#
CT_KERNEL_LINUX_PKG_KSYM="LINUX"
CT_LINUX_DIR_NAME="linux"
CT_LINUX_PKG_NAME="linux"
CT_LINUX_SRC_RELEASE=y
CT_LINUX_PATCH_ORDER="global"
# CT_LINUX_V_4_20 is not set
# CT_LINUX_V_4_19 is not set
# CT_LINUX_V_4_18 is not set
# CT_LINUX_V_4_17 is not set
# CT_LINUX_V_4_16 is not set
# CT_LINUX_V_4_15 is not set
# CT_LINUX_V_4_14 is not set
# CT_LINUX_V_4_13 is not set
# CT_LINUX_V_4_12 is not set
# CT_LINUX_V_4_11 is not set
# CT_LINUX_V_4_10 is not set
# CT_LINUX_V_4_9 is not set
# CT_LINUX_V_4_4 is not set
# CT_LINUX_V_4_1 is not set
# CT_LINUX_V_3_16 is not set
# CT_LINUX_V_3_13 is not set
# CT_LINUX_V_3_12 is not set
# CT_LINUX_V_3_10 is not set
# CT_LINUX_V_3_4 is not set
CT_LINUX_V_3_2=y
# CT_LINUX_V_2_6_32 is not set
# CT_LINUX_NO_VERSIONS is not set
CT_LINUX_VERSION="3.2.101"
CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
CT_LINUX_4_8_or_older=y
CT_LINUX_older_than_4_8=y
CT_LINUX_3_7_or_older=y
CT_LINUX_older_than_3_7=y
CT_LINUX_later_than_3_2=y
CT_LINUX_3_2_or_later=y
CT_KERNEL_LINUX_VERBOSITY_0=y
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
CT_KERNEL_LINUX_INSTALL_CHECK=y
CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
#
# Common kernel options
#
CT_SHARED_LIBS=y
#
# linux other options
#
CT_KERNEL_LINUX_VERBOSITY_0=y
# CT_KERNEL_LINUX_VERBOSITY_1 is not set
# CT_KERNEL_LINUX_VERBOSITY_2 is not set
CT_KERNEL_LINUX_VERBOSE_LEVEL=0
CT_KERNEL_LINUX_INSTALL_CHECK=y
#
# Binary utilities
#
CT_ARCH_BINFMT_ELF=y
CT_BINUTILS_BINUTILS=y
CT_BINUTILS="binutils"
CT_BINUTILS_binutils=y
CT_BINUTILS_CHOICE_KSYM="BINUTILS"
CT_BINUTILS_BINUTILS_SHOW=y
#
# Options for binutils
#
CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
CT_BINUTILS_DIR_NAME="binutils"
CT_BINUTILS_USE_GNU=y
CT_BINUTILS_USE="BINUTILS"
CT_BINUTILS_PKG_NAME="binutils"
CT_BINUTILS_SRC_RELEASE=y
CT_BINUTILS_PATCH_ORDER="global"
CT_BINUTILS_V_2_32=y
# CT_BINUTILS_V_2_31 is not set
# CT_BINUTILS_V_2_30 is not set
# CT_BINUTILS_V_2_29 is not set
# CT_BINUTILS_V_2_28 is not set
# CT_BINUTILS_V_2_27 is not set
# CT_BINUTILS_V_2_26 is not set
# CT_BINUTILS_NO_VERSIONS is not set
CT_BINUTILS_VERSION="2.32"
CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
CT_BINUTILS_later_than_2_30=y
CT_BINUTILS_2_30_or_later=y
CT_BINUTILS_later_than_2_27=y
CT_BINUTILS_2_27_or_later=y
CT_BINUTILS_later_than_2_25=y
CT_BINUTILS_2_25_or_later=y
CT_BINUTILS_later_than_2_23=y
CT_BINUTILS_2_23_or_later=y
#
# GNU binutils
#
# CT_CC_BINUTILS_SHOW_LINARO is not set
CT_BINUTILS_V_2_25_1=y
# CT_BINUTILS_V_2_25 is not set
# CT_BINUTILS_V_2_24 is not set
# CT_BINUTILS_V_2_23_2 is not set
# CT_BINUTILS_V_2_23_1 is not set
# CT_BINUTILS_V_2_22 is not set
# CT_BINUTILS_V_2_21_53 is not set
# CT_BINUTILS_V_2_21_1a is not set
# CT_BINUTILS_V_2_20_1a is not set
# CT_BINUTILS_V_2_19_1a is not set
# CT_BINUTILS_V_2_18a is not set
CT_BINUTILS_VERSION="2.25.1"
CT_BINUTILS_2_25_1_or_later=y
CT_BINUTILS_2_25_or_later=y
CT_BINUTILS_2_24_or_later=y
CT_BINUTILS_2_23_or_later=y
CT_BINUTILS_2_22_or_later=y
CT_BINUTILS_2_21_or_later=y
CT_BINUTILS_2_20_or_later=y
CT_BINUTILS_2_19_or_later=y
CT_BINUTILS_2_18_or_later=y
CT_BINUTILS_HAS_HASH_STYLE=y
CT_BINUTILS_HAS_GOLD=y
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_GOLD_SUPPORT=y
CT_BINUTILS_HAS_PLUGINS=y
CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
CT_BINUTILS_FORCE_LD_BFD=y
CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
CT_BINUTILS_GOLD_SUPPORT=y
CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
CT_BINUTILS_LINKER_LD=y
# CT_BINUTILS_LINKER_LD_GOLD is not set
# CT_BINUTILS_LINKER_GOLD_LD is not set
CT_BINUTILS_LINKERS_LIST="ld"
CT_BINUTILS_LINKER_DEFAULT="bfd"
# CT_BINUTILS_PLUGINS is not set
CT_BINUTILS_RELRO=m
CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
# CT_BINUTILS_FOR_TARGET is not set
#
# binutils other options
#
CT_ALL_BINUTILS_CHOICES="BINUTILS"
#
# C-library
#
CT_LIBC_GLIBC=y
# CT_LIBC_NEWLIB is not set
# CT_LIBC_NONE is not set
# CT_LIBC_UCLIBC is not set
CT_LIBC="glibc"
CT_LIBC_VERSION="2.16.0"
CT_LIBC_glibc=y
# CT_LIBC_musl is not set
# CT_LIBC_uClibc is not set
CT_LIBC_avr_libc_AVAILABLE=y
CT_LIBC_glibc_AVAILABLE=y
CT_LIBC_CHOICE_KSYM="GLIBC"
CT_THREADS="nptl"
# CT_CC_GLIBC_SHOW_LINARO is not set
# CT_LIBC_GLIBC_V_2_22 is not set
# CT_LIBC_GLIBC_V_2_21 is not set
# CT_LIBC_GLIBC_V_2_20 is not set
# CT_LIBC_GLIBC_V_2_19 is not set
# CT_LIBC_GLIBC_V_2_18 is not set
# CT_LIBC_GLIBC_V_2_17 is not set
CT_LIBC_GLIBC_V_2_16_0=y
# CT_LIBC_GLIBC_V_2_15 is not set
# CT_LIBC_GLIBC_V_2_14_1 is not set
# CT_LIBC_GLIBC_V_2_14 is not set
# CT_LIBC_GLIBC_V_2_13 is not set
# CT_LIBC_GLIBC_V_2_12_2 is not set
# CT_LIBC_GLIBC_V_2_12_1 is not set
# CT_LIBC_GLIBC_V_2_11_1 is not set
# CT_LIBC_GLIBC_V_2_11 is not set
# CT_LIBC_GLIBC_V_2_10_1 is not set
# CT_LIBC_GLIBC_V_2_9 is not set
# CT_LIBC_GLIBC_V_2_8 is not set
CT_LIBC_mingw_AVAILABLE=y
CT_LIBC_musl_AVAILABLE=y
CT_LIBC_newlib_AVAILABLE=y
CT_LIBC_none_AVAILABLE=y
CT_LIBC_uClibc_AVAILABLE=y
CT_LIBC_GLIBC_SHOW=y
#
# Options for glibc
#
CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
CT_GLIBC_DIR_NAME="glibc"
CT_GLIBC_USE_GNU=y
CT_GLIBC_USE="GLIBC"
CT_GLIBC_PKG_NAME="glibc"
CT_GLIBC_SRC_RELEASE=y
CT_GLIBC_PATCH_ORDER="global"
# CT_GLIBC_V_2_28 is not set
# CT_GLIBC_V_2_27 is not set
# CT_GLIBC_V_2_26 is not set
# CT_GLIBC_V_2_25 is not set
# CT_GLIBC_V_2_24 is not set
# CT_GLIBC_V_2_23 is not set
# CT_GLIBC_V_2_19 is not set
CT_GLIBC_V_2_17=y
# CT_GLIBC_V_2_12_1 is not set
# CT_GLIBC_NO_VERSIONS is not set
CT_GLIBC_VERSION="2.17"
CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
CT_GLIBC_2_29_or_older=y
CT_GLIBC_older_than_2_29=y
CT_GLIBC_REQUIRE_older_than_2_29=y
CT_GLIBC_2_27_or_older=y
CT_GLIBC_older_than_2_27=y
CT_GLIBC_2_26_or_older=y
CT_GLIBC_older_than_2_26=y
CT_GLIBC_2_25_or_older=y
CT_GLIBC_older_than_2_25=y
CT_GLIBC_2_24_or_older=y
CT_GLIBC_older_than_2_24=y
CT_GLIBC_2_23_or_older=y
CT_GLIBC_older_than_2_23=y
CT_GLIBC_2_20_or_older=y
CT_GLIBC_older_than_2_20=y
CT_GLIBC_2_17_or_later=y
CT_GLIBC_2_17_or_older=y
CT_GLIBC_later_than_2_14=y
CT_GLIBC_2_14_or_later=y
CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
CT_GLIBC_DEP_BINUTILS=y
CT_GLIBC_DEP_GCC=y
CT_GLIBC_DEP_PYTHON=y
CT_GLIBC_HAS_NPTL_ADDON=y
CT_GLIBC_HAS_PORTS_ADDON=y
CT_GLIBC_HAS_LIBIDN_ADDON=y
CT_GLIBC_USE_PORTS_ADDON=y
CT_GLIBC_USE_NPTL_ADDON=y
# CT_GLIBC_USE_LIBIDN_ADDON is not set
CT_GLIBC_HAS_OBSOLETE_RPC=y
CT_GLIBC_EXTRA_CONFIG_ARRAY=""
CT_GLIBC_CONFIGPARMS=""
CT_GLIBC_EXTRA_CFLAGS=""
CT_GLIBC_ENABLE_OBSOLETE_RPC=y
# CT_GLIBC_DISABLE_VERSIONING is not set
CT_GLIBC_OLDEST_ABI=""
CT_GLIBC_FORCE_UNWIND=y
# CT_GLIBC_LOCALES is not set
# CT_GLIBC_KERNEL_VERSION_NONE is not set
CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
CT_GLIBC_MIN_KERNEL="3.2.101"
# CT_GLIBC_SSP_DEFAULT is not set
# CT_GLIBC_SSP_NO is not set
# CT_GLIBC_SSP_YES is not set
# CT_GLIBC_SSP_ALL is not set
# CT_GLIBC_SSP_STRONG is not set
# CT_NEWLIB_USE_REDHAT is not set
CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
CT_LIBC_SUPPORT_THREADS_ANY=y
CT_LIBC_SUPPORT_THREADS_NATIVE=y
@ -343,100 +462,71 @@ CT_LIBC_SUPPORT_THREADS_NATIVE=y
# Common C library options
#
CT_THREADS_NATIVE=y
# CT_CREATE_LDSO_CONF is not set
CT_LIBC_XLDD=y
#
# glibc other options
#
CT_LIBC_GLIBC_PORTS_EXTERNAL=y
CT_LIBC_GLIBC_MAY_FORCE_PORTS=y
CT_LIBC_glibc_familly=y
CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY=""
CT_LIBC_GLIBC_CONFIGPARMS=""
CT_LIBC_GLIBC_EXTRA_CFLAGS=""
CT_LIBC_EXTRA_CC_ARGS=""
# CT_LIBC_DISABLE_VERSIONING is not set
CT_LIBC_OLDEST_ABI=""
CT_LIBC_GLIBC_FORCE_UNWIND=y
CT_LIBC_GLIBC_USE_PORTS=y
CT_LIBC_ADDONS_LIST=""
#
# WARNING !!!
#
#
# For glibc >= 2.8, it can happen that the tarballs
#
#
# for the addons are not available for download.
#
#
# If that happens, bad luck... Try a previous version
#
#
# or try again later... :-(
#
# CT_LIBC_LOCALES is not set
# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set
CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y
# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set
CT_LIBC_GLIBC_MIN_KERNEL="3.2.72"
#
# C compiler
#
CT_CC="gcc"
CT_CC_CORE_PASSES_NEEDED=y
CT_CC_CORE_PASS_1_NEEDED=y
CT_CC_CORE_PASS_2_NEEDED=y
CT_CC_gcc=y
# CT_CC_GCC_SHOW_LINARO is not set
CT_CC_GCC_V_5_2_0=y
# CT_CC_GCC_V_4_9_3 is not set
# CT_CC_GCC_V_4_8_5 is not set
# CT_CC_GCC_V_4_7_4 is not set
# CT_CC_GCC_V_4_6_4 is not set
# CT_CC_GCC_V_4_5_4 is not set
# CT_CC_GCC_V_4_4_7 is not set
# CT_CC_GCC_V_4_3_6 is not set
# CT_CC_GCC_V_4_2_4 is not set
CT_CC_GCC_4_2_or_later=y
CT_CC_GCC_4_3_or_later=y
CT_CC_GCC_4_4_or_later=y
CT_CC_GCC_4_5_or_later=y
CT_CC_GCC_4_6_or_later=y
CT_CC_GCC_4_7_or_later=y
CT_CC_GCC_4_8_or_later=y
CT_CC_GCC_4_9_or_later=y
CT_CC_GCC_5=y
CT_CC_GCC_5_or_later=y
CT_CC_GCC_HAS_GRAPHITE=y
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_HAS_LTO=y
CT_CC_GCC_USE_LTO=y
CT_CC_GCC_HAS_PKGVERSION_BUGURL=y
CT_CC_GCC_HAS_BUILD_ID=y
CT_CC_GCC_HAS_LNK_HASH_STYLE=y
CT_CC_GCC_USE_GMP_MPFR=y
CT_CC_GCC_USE_MPC=y
CT_CC_GCC_HAS_LIBQUADMATH=y
CT_CC_GCC_HAS_LIBSANITIZER=y
CT_CC_GCC_VERSION="5.2.0"
# CT_CC_LANG_FORTRAN is not set
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_SUPPORT_GOLANG=y
CT_CC_GCC=y
CT_CC="gcc"
CT_CC_CHOICE_KSYM="GCC"
CT_CC_GCC_SHOW=y
#
# Options for gcc
#
CT_CC_GCC_PKG_KSYM="GCC"
CT_GCC_DIR_NAME="gcc"
CT_GCC_USE_GNU=y
CT_GCC_USE="GCC"
CT_GCC_PKG_NAME="gcc"
CT_GCC_SRC_RELEASE=y
CT_GCC_PATCH_ORDER="global"
CT_GCC_V_8=y
# CT_GCC_V_7 is not set
# CT_GCC_V_6 is not set
# CT_GCC_V_5 is not set
# CT_GCC_V_4_9 is not set
# CT_GCC_NO_VERSIONS is not set
CT_GCC_VERSION="8.3.0"
CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_GCC_SIGNATURE_FORMAT=""
CT_GCC_later_than_7=y
CT_GCC_7_or_later=y
CT_GCC_later_than_6=y
CT_GCC_6_or_later=y
CT_GCC_later_than_5=y
CT_GCC_5_or_later=y
CT_GCC_later_than_4_9=y
CT_GCC_4_9_or_later=y
CT_GCC_later_than_4_8=y
CT_GCC_4_8_or_later=y
CT_CC_GCC_HAS_LIBMPX=y
CT_CC_GCC_ENABLE_CXX_FLAGS=""
CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
CT_CC_GCC_EXTRA_ENV_ARRAY=""
CT_CC_GCC_STATIC_LIBSTDCXX=y
# CT_CC_GCC_SYSTEM_ZLIB is not set
CT_CC_GCC_CONFIG_TLS=m
#
# Optimisation features
#
CT_CC_GCC_USE_GRAPHITE=y
CT_CC_GCC_USE_LTO=y
#
# Settings for libraries running on target
@ -465,97 +555,208 @@ CT_CC_GCC_DEC_FLOAT_AUTO=y
# CT_CC_GCC_DEC_FLOAT_BID is not set
# CT_CC_GCC_DEC_FLOAT_DPD is not set
# CT_CC_GCC_DEC_FLOATS_NO is not set
CT_CC_SUPPORT_CXX=y
CT_CC_SUPPORT_FORTRAN=y
CT_CC_SUPPORT_JAVA=y
CT_CC_SUPPORT_ADA=y
CT_CC_SUPPORT_OBJC=y
CT_CC_SUPPORT_OBJCXX=y
CT_CC_SUPPORT_GOLANG=y
CT_ALL_CC_CHOICES="GCC"
#
# Additional supported languages:
#
CT_CC_LANG_CXX=y
# CT_CC_LANG_JAVA is not set
# CT_CC_LANG_FORTRAN is not set
#
# Debug facilities
#
# CT_DEBUG_dmalloc is not set
# CT_DEBUG_duma is not set
# CT_DEBUG_gdb is not set
# CT_DEBUG_ltrace is not set
# CT_DEBUG_strace is not set
# CT_DEBUG_DUMA is not set
# CT_DEBUG_GDB is not set
# CT_DEBUG_LTRACE is not set
# CT_DEBUG_STRACE is not set
CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
#
# Companion libraries
#
CT_COMPLIBS_NEEDED=y
# CT_COMPLIBS_CHECK is not set
# CT_COMP_LIBS_CLOOG is not set
# CT_COMP_LIBS_EXPAT is not set
CT_COMP_LIBS_GETTEXT=y
CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
CT_GETTEXT_DIR_NAME="gettext"
CT_GETTEXT_PKG_NAME="gettext"
CT_GETTEXT_SRC_RELEASE=y
CT_GETTEXT_PATCH_ORDER="global"
CT_GETTEXT_V_0_19_8_1=y
# CT_GETTEXT_NO_VERSIONS is not set
CT_GETTEXT_VERSION="0.19.8.1"
CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
CT_COMP_LIBS_GMP=y
CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
CT_GMP_DIR_NAME="gmp"
CT_GMP_PKG_NAME="gmp"
CT_GMP_SRC_RELEASE=y
CT_GMP_PATCH_ORDER="global"
CT_GMP_V_6_1=y
# CT_GMP_NO_VERSIONS is not set
CT_GMP_VERSION="6.1.2"
CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
CT_GMP_SIGNATURE_FORMAT="packed/.sig"
CT_GMP_later_than_5_1_0=y
CT_GMP_5_1_0_or_later=y
CT_GMP_later_than_5_0_0=y
CT_GMP_5_0_0_or_later=y
CT_GMP_REQUIRE_5_0_0_or_later=y
CT_COMP_LIBS_ISL=y
CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
CT_ISL_DIR_NAME="isl"
CT_ISL_PKG_NAME="isl"
CT_ISL_SRC_RELEASE=y
CT_ISL_PATCH_ORDER="global"
CT_ISL_V_0_20=y
# CT_ISL_V_0_19 is not set
# CT_ISL_V_0_18 is not set
# CT_ISL_V_0_17 is not set
# CT_ISL_V_0_16 is not set
# CT_ISL_V_0_15 is not set
# CT_ISL_NO_VERSIONS is not set
CT_ISL_VERSION="0.20"
CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
CT_ISL_SIGNATURE_FORMAT=""
CT_ISL_later_than_0_18=y
CT_ISL_0_18_or_later=y
CT_ISL_later_than_0_15=y
CT_ISL_0_15_or_later=y
CT_ISL_REQUIRE_0_15_or_later=y
CT_ISL_later_than_0_14=y
CT_ISL_0_14_or_later=y
CT_ISL_REQUIRE_0_14_or_later=y
CT_ISL_later_than_0_13=y
CT_ISL_0_13_or_later=y
CT_ISL_later_than_0_12=y
CT_ISL_0_12_or_later=y
CT_ISL_REQUIRE_0_12_or_later=y
# CT_COMP_LIBS_LIBELF is not set
CT_COMP_LIBS_LIBICONV=y
CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
CT_LIBICONV_DIR_NAME="libiconv"
CT_LIBICONV_PKG_NAME="libiconv"
CT_LIBICONV_SRC_RELEASE=y
CT_LIBICONV_PATCH_ORDER="global"
CT_LIBICONV_V_1_15=y
# CT_LIBICONV_NO_VERSIONS is not set
CT_LIBICONV_VERSION="1.15"
CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
CT_COMP_LIBS_MPC=y
CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
CT_MPC_DIR_NAME="mpc"
CT_MPC_PKG_NAME="mpc"
CT_MPC_SRC_RELEASE=y
CT_MPC_PATCH_ORDER="global"
CT_MPC_V_1_1=y
# CT_MPC_V_1_0 is not set
# CT_MPC_NO_VERSIONS is not set
CT_MPC_VERSION="1.1.0"
CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPC_ARCHIVE_FORMATS=".tar.gz"
CT_MPC_SIGNATURE_FORMAT="packed/.sig"
CT_MPC_1_1_0_or_later=y
CT_MPC_1_1_0_or_older=y
CT_COMP_LIBS_MPFR=y
CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
CT_MPFR_DIR_NAME="mpfr"
CT_MPFR_PKG_NAME="mpfr"
CT_MPFR_SRC_RELEASE=y
CT_MPFR_PATCH_ORDER="global"
CT_MPFR_V_4_0=y
# CT_MPFR_V_3_1 is not set
# CT_MPFR_NO_VERSIONS is not set
CT_MPFR_VERSION="4.0.2"
CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
CT_MPFR_later_than_4_0_0=y
CT_MPFR_4_0_0_or_later=y
CT_MPFR_later_than_3_0_0=y
CT_MPFR_3_0_0_or_later=y
CT_MPFR_REQUIRE_3_0_0_or_later=y
CT_COMP_LIBS_NCURSES=y
CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
CT_NCURSES_DIR_NAME="ncurses"
CT_NCURSES_PKG_NAME="ncurses"
CT_NCURSES_SRC_RELEASE=y
CT_NCURSES_PATCH_ORDER="global"
CT_NCURSES_V_6_1=y
# CT_NCURSES_V_6_0 is not set
# CT_NCURSES_NO_VERSIONS is not set
CT_NCURSES_VERSION="6.1"
CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
CT_NCURSES_HOST_CONFIG_ARGS=""
CT_NCURSES_HOST_DISABLE_DB=y
CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
CT_NCURSES_TARGET_CONFIG_ARGS=""
# CT_NCURSES_TARGET_DISABLE_DB is not set
CT_NCURSES_TARGET_FALLBACKS=""
CT_COMP_LIBS_ZLIB=y
CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
CT_ZLIB_DIR_NAME="zlib"
CT_ZLIB_PKG_NAME="zlib"
CT_ZLIB_SRC_RELEASE=y
CT_ZLIB_PATCH_ORDER="global"
CT_ZLIB_V_1_2_11=y
# CT_ZLIB_NO_VERSIONS is not set
CT_ZLIB_VERSION="1.2.11"
CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
CT_LIBICONV_NEEDED=y
CT_GETTEXT_NEEDED=y
CT_GMP_NEEDED=y
CT_MPFR_NEEDED=y
CT_ISL_NEEDED=y
CT_MPC_NEEDED=y
CT_COMPLIBS=y
CT_NCURSES_NEEDED=y
CT_ZLIB_NEEDED=y
CT_LIBICONV=y
CT_GETTEXT=y
CT_GMP=y
CT_MPFR=y
CT_ISL=y
CT_MPC=y
CT_LIBICONV_V_1_14=y
CT_LIBICONV_VERSION="1.14"
CT_GETTEXT_V_0_19_6=y
CT_GETTEXT_VERSION="0.19.6"
CT_GMP_V_6_0_0=y
# CT_GMP_V_5_1_3 is not set
# CT_GMP_V_5_1_1 is not set
# CT_GMP_V_5_0_2 is not set
# CT_GMP_V_5_0_1 is not set
# CT_GMP_V_4_3_2 is not set
# CT_GMP_V_4_3_1 is not set
# CT_GMP_V_4_3_0 is not set
CT_GMP_5_0_2_or_later=y
CT_GMP_VERSION="6.0.0a"
CT_MPFR_V_3_1_3=y
# CT_MPFR_V_3_1_2 is not set
# CT_MPFR_V_3_1_0 is not set
# CT_MPFR_V_3_0_1 is not set
# CT_MPFR_V_3_0_0 is not set
# CT_MPFR_V_2_4_2 is not set
# CT_MPFR_V_2_4_1 is not set
# CT_MPFR_V_2_4_0 is not set
CT_MPFR_VERSION="3.1.3"
CT_ISL_V_0_14=y
# CT_ISL_V_0_12_2 is not set
CT_ISL_V_0_14_or_later=y
CT_ISL_V_0_12_or_later=y
CT_ISL_VERSION="0.14"
# CT_CLOOG_V_0_18_4 is not set
# CT_CLOOG_V_0_18_1 is not set
# CT_CLOOG_V_0_18_0 is not set
CT_MPC_V_1_0_3=y
# CT_MPC_V_1_0_2 is not set
# CT_MPC_V_1_0_1 is not set
# CT_MPC_V_1_0 is not set
# CT_MPC_V_0_9 is not set
# CT_MPC_V_0_8_2 is not set
# CT_MPC_V_0_8_1 is not set
# CT_MPC_V_0_7 is not set
CT_MPC_VERSION="1.0.3"
#
# Companion libraries common options
#
# CT_COMPLIBS_CHECK is not set
CT_NCURSES=y
CT_ZLIB=y
#
# Companion tools
#
#
# READ HELP before you say 'Y' below !!!
#
# CT_COMP_TOOLS is not set
# CT_COMP_TOOLS_FOR_HOST is not set
# CT_COMP_TOOLS_AUTOCONF is not set
# CT_COMP_TOOLS_AUTOMAKE is not set
# CT_COMP_TOOLS_BISON is not set
# CT_COMP_TOOLS_DTC is not set
# CT_COMP_TOOLS_LIBTOOL is not set
# CT_COMP_TOOLS_M4 is not set
# CT_COMP_TOOLS_MAKE is not set
CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"

View File

@ -1,48 +0,0 @@
commit bdb24c2851fd5f0ad9b82d7ea1db911d334b02d2
Author: Joseph Myers <joseph@codesourcery.com>
Date: Tue May 20 21:27:13 2014 +0000
Fix ARM build with GCC trunk.
sysdeps/unix/sysv/linux/arm/unwind-resume.c and
sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c have static
variables that are written in C code but only read from toplevel asms.
Current GCC trunk now optimizes away such apparently write-only static
variables, so causing a build failure. This patch marks those
variables with __attribute_used__ to avoid that optimization.
Tested that this fixes the build for ARM.
* sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c
(libgcc_s_resume): Use __attribute_used__.
* sysdeps/unix/sysv/linux/arm/unwind-resume.c (libgcc_s_resume):
Likewise.
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
index 29e2c2b00b04..e848bfeffdcb 100644
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c
@@ -22,7 +22,8 @@
#include <pthreadP.h>
static void *libgcc_s_handle;
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
+ __attribute_used__;
static _Unwind_Reason_Code (*libgcc_s_personality)
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);
static _Unwind_Reason_Code (*libgcc_s_forcedunwind)
diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
index 285b99b5ed0d..48d00fc83641 100644
--- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c
@@ -20,7 +20,8 @@
#include <stdio.h>
#include <unwind.h>
-static void (*libgcc_s_resume) (struct _Unwind_Exception *exc);
+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc)
+ __attribute_used__;
static _Unwind_Reason_Code (*libgcc_s_personality)
(_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *);

View File

@ -3,8 +3,8 @@ FROM ubuntu:16.04
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh
COPY dist-armv7-linux/crosstool-ng.sh /scripts/
RUN sh /scripts/crosstool-ng.sh
COPY scripts/crosstool-ng-1.24.sh /scripts/
RUN sh /scripts/crosstool-ng-1.24.sh
COPY scripts/rustbuild-setup.sh /scripts/
RUN sh /scripts/rustbuild-setup.sh

View File

@ -72,6 +72,9 @@ RUN ./install-mips-musl.sh
COPY dist-various-1/install-mipsel-musl.sh /build
RUN ./install-mipsel-musl.sh
COPY dist-various-1/install-aarch64-none-elf.sh /build
RUN ./install-aarch64-none-elf.sh
# Suppress some warnings in the openwrt toolchains we downloaded
ENV STAGING_DIR=/tmp
@ -140,6 +143,8 @@ ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi
ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi
ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl
ENV TARGETS=$TARGETS,aarch64-unknown-none
ENV TARGETS=$TARGETS,aarch64-unknown-none-softfloat
ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
ENV TARGETS=$TARGETS,x86_64-unknown-redox
ENV TARGETS=$TARGETS,thumbv6m-none-eabi
@ -178,6 +183,10 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CC_armv7a_none_eabihf=arm-none-eabi-gcc \
CFLAGS_armv7a_none_eabi=-march=armv7-a \
CFLAGS_armv7a_none_eabihf=-march=armv7-a+vfpv3 \
CC_aarch64_unknown_none_softfloat=aarch64-none-elf-gcc \
CFLAGS_aarch64_unknown_none_softfloat=-mstrict-align -march=armv8-a+nofp+nosimd \
CC_aarch64_unknown_none=aarch64-none-elf-gcc \
CFLAGS_aarch64_unknown_none=-mstrict-align -march=armv8-a+fp+simd \
CC_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-gcc \
AR_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-ar \
CXX_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-g++ \

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
curl -L https://developer.arm.com/-/media/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-aarch64-none-elf.tar.xz \
| tar --extract --xz --strip 1 --directory /usr/local

View File

@ -103,6 +103,7 @@ x--expand-yaml-anchors--remove:
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
with:
github_token: "${{ secrets.github_token }}"
if: success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'
<<: *step
- name: add extra environment variables

@ -1 +1 @@
Subproject commit 6fb3705e5230311b096d47f7e2c91f9ce24393d0
Subproject commit c8841f2841a2d26124319ddadd1b6a245f9a1856

@ -1 +1 @@
Subproject commit 9f797e65e6bcc79419975b17aff8e21c9adc039f
Subproject commit 411197b0e77590c967e37e8f6ec681abd359afe8

@ -1 +1 @@
Subproject commit e2f11fe4d6a5ecb471c70323197da43c70cb96b6
Subproject commit 89dd146154474559536d5d4049a03831c501deea

@ -1 +1 @@
Subproject commit cb369ae95ca36b841960182d26f6d5d9b2e3cc18
Subproject commit edd2a7e687358712608896730c083cb76c7b401a

View File

@ -257,9 +257,8 @@ them in parallel. Increasing parallelism may speed up compile times, but may
also produce slower code. Setting this to 1 may improve the performance of
generated code, but may be slower to compile.
The default, if not specified, is 16. This flag is ignored if
[incremental](#incremental) is enabled, in which case an internal heuristic is
used to split the crate.
The default, if not specified, is 16 for non-incremental builds. For
incremental builds the default is 256 which allows caching to be more granular.
## remark

View File

@ -1,3 +1,6 @@
[book]
title = "The Rust Unstable Book"
author = "The Rust Community"
[output.html]
git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/unstable-book"

View File

@ -6,144 +6,75 @@ The tracking issue for this feature is: [#39699](https://github.com/rust-lang/ru
This feature allows for use of one of following sanitizers:
* [AddressSanitizer][clang-asan] a faster memory error detector. Can
detect out-of-bounds access to heap, stack, and globals, use after free, use
after return, double free, invalid free, memory leaks.
* [AddressSanitizer][clang-asan] a fast memory error detector.
* [LeakSanitizer][clang-lsan] a run-time memory leak detector.
* [MemorySanitizer][clang-msan] a detector of uninitialized reads.
* [ThreadSanitizer][clang-tsan] a fast data race detector.
To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one
of `address`, `leak`, `memory` or `thread`.
To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=leak`,
`-Zsanitizer=memory` or `-Zsanitizer=thread`. Only a single sanitizer can be
enabled at a time.
# Examples
# AddressSanitizer
This sections show various issues that can be detected with sanitizers. For
simplicity, the examples are prepared under assumption that optimization level
used is zero.
AddressSanitizer is a memory error detector. It can detect the following types
of bugs:
## AddressSanitizer
* Out of bound accesses to heap, stack and globals
* Use after free
* Use after return (runtime flag `ASAN_OPTIONS=detect_stack_use_after_return=1`)
* Use after scope
* Double-free, invalid free
* Memory leaks
AddressSanitizer is supported on the following targets:
* `x86_64-apple-darwin`
* `x86_64-unknown-linux-gnu`
AddressSanitizer works with non-instrumented code although it will impede its
ability to detect some bugs. It is not expected to produce false positive
reports.
## Examples
Stack buffer overflow:
```shell
$ cat a.rs
```rust
fn main() {
let xs = [0, 1, 2, 3];
let _y = unsafe { *xs.as_ptr().offset(4) };
}
$ rustc -Zsanitizer=address a.rs
$ ./a
=================================================================
==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388
READ of size 4 at 0x7ffcc15f43d0 thread T0
#0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4)
#1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb)
#2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12
#3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39
#4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7
#5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12
#6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8
#7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24
#8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61)
#9 0x55f77dc0163a in main (/tmp/a+0xa63a)
#10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
#11 0x55f77dc01289 in _start (/tmp/a+0xa289)
Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame
#0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f)
This frame has 1 object(s):
[32, 48) 'xs' <== Memory access at offset 48 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac
Shadow bytes around the buggy address:
0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==10029==ABORTING
```
Use of a stack object after its scope has already ended:
```shell
$ cat b.rs
static mut P: *mut usize = std::ptr::null_mut();
$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
==37882==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe400e6250 at pc 0x5609a841fb20 bp 0x7ffe400e6210 sp 0x7ffe400e6208
READ of size 4 at 0x7ffe400e6250 thread T0
#0 0x5609a841fb1f in example::main::h628ffc6626ed85b2 /.../src/main.rs:3:23
...
fn main() {
unsafe {
{
let mut x = 0;
P = &mut x;
}
std::ptr::write_volatile(P, 123);
}
}
$ rustc -Zsanitizer=address b.rs
$./b
=================================================================
==424427==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fff67be6be0 at pc 0x5647a3ea4658 bp 0x7fff67be6b90 sp 0x7fff67be6b88
WRITE of size 8 at 0x7fff67be6be0 thread T0
#0 0x5647a3ea4657 in core::ptr::write_volatile::h4b04601757d0376d (/tmp/b+0xb8657)
#1 0x5647a3ea4432 in b::main::h5574a756e615c9cf (/tmp/b+0xb8432)
#2 0x5647a3ea480b in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd57e7ee01866077e (/tmp/b+0xb880b)
#3 0x5647a3eab412 in std::panicking::try::do_call::he0421ca82dd11ba3 (.llvm.8083791802951296215) (/tmp/b+0xbf412)
#4 0x5647a3eacb26 in __rust_maybe_catch_panic (/tmp/b+0xc0b26)
#5 0x5647a3ea5b66 in std::rt::lang_start_internal::h19bc96b28f670a64 (/tmp/b+0xb9b66)
#6 0x5647a3ea4788 in std::rt::lang_start::h642d10b4b6965fb8 (/tmp/b+0xb8788)
#7 0x5647a3ea449a in main (/tmp/b+0xb849a)
#8 0x7fd1d18b3bba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba)
#9 0x5647a3df7299 in _start (/tmp/b+0xb299)
Address 0x7fff67be6be0 is located in stack of thread T0 at offset 32 in frame
#0 0x5647a3ea433f in b::main::h5574a756e615c9cf (/tmp/b+0xb833f)
Address 0x7ffe400e6250 is located in stack of thread T0 at offset 48 in frame
#0 0x5609a841f8af in example::main::h628ffc6626ed85b2 /.../src/main.rs:1
This frame has 1 object(s):
[32, 40) 'x' <== Memory access at offset 32 is inside this variable
[32, 48) 'xs' (line 2) <== Memory access at offset 48 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope (/tmp/b+0xb8657) in core::ptr::write_volatile::h4b04601757d0376d
SUMMARY: AddressSanitizer: stack-buffer-overflow /.../src/main.rs:3:23 in example::main::h628ffc6626ed85b2
Shadow bytes around the buggy address:
0x10006cf74d20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74d30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74d40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74d50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74d60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10006cf74d70: 00 00 00 00 00 00 00 00 f1 f1 f1 f1[f8]f3 f3 f3
0x10006cf74d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10006cf74dc0: f1 f1 f1 f1 00 f3 f3 f3 00 00 00 00 00 00 00 00
0x100048014bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100048014c40: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00
0x100048014c50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100048014c70: f1 f1 f1 f1 00 00 f3 f3 00 00 00 00 00 00 00 00
0x100048014c80: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x100048014c90: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
@ -164,17 +95,95 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==424427==ABORTING
==37882==ABORTING
```
## MemorySanitizer
Use of a stack object after its scope has already ended:
Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument
the standard library, and passing `-Zsanitizer-track-origins` to track the
origins of uninitialized memory:
```rust
static mut P: *mut usize = std::ptr::null_mut();
fn main() {
unsafe {
{
let mut x = 0;
P = &mut x;
}
std::ptr::write_volatile(P, 123);
}
}
```
```shell
$ cat src/main.rs
$ export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address
$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
=================================================================
==39249==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7ffc7ed3e1a0 at pc 0x55c98b262a8e bp 0x7ffc7ed3e050 sp 0x7ffc7ed3e048
WRITE of size 8 at 0x7ffc7ed3e1a0 thread T0
#0 0x55c98b262a8d in core::ptr::write_volatile::he21f1df5a82f329a /.../src/rust/src/libcore/ptr/mod.rs:1048:5
#1 0x55c98b262cd2 in example::main::h628ffc6626ed85b2 /.../src/main.rs:9:9
...
Address 0x7ffc7ed3e1a0 is located in stack of thread T0 at offset 32 in frame
#0 0x55c98b262bdf in example::main::h628ffc6626ed85b2 /.../src/main.rs:3
This frame has 1 object(s):
[32, 40) 'x' (line 6) <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope /.../src/rust/src/libcore/ptr/mod.rs:1048:5 in core::ptr::write_volatile::he21f1df5a82f329a
Shadow bytes around the buggy address:
0x10000fd9fbe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000fd9fbf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000fd9fc00: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x10000fd9fc10: f8 f8 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x10000fd9fc20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10000fd9fc30: f1 f1 f1 f1[f8]f3 f3 f3 00 00 00 00 00 00 00 00
0x10000fd9fc40: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
0x10000fd9fc50: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
0x10000fd9fc60: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3
0x10000fd9fc70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10000fd9fc80: 00 00 00 00 f1 f1 f1 f1 00 00 f3 f3 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==39249==ABORTING
```
# MemorySanitizer
MemorySanitizer is detector of uninitialized reads. It is only supported on the
`x86_64-unknown-linux-gnu` target.
MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
achieve that will result in false positive reports.
## Example
Detecting the use of uninitialized memory. The `-Zbuild-std` flag rebuilds and
instruments the standard library, and is strictly necessary for the correct
operation of the tool. The `-Zsanitizer-track-origins` enables tracking of the
origins of uninitialized memory:
```rust
use std::mem::MaybeUninit;
fn main() {
@ -184,7 +193,9 @@ fn main() {
println!("{}", a[2]);
}
}
```
```shell
$ export \
CC=clang \
CXX=clang++ \
@ -193,7 +204,7 @@ $ export \
RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \
RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
$ cargo clean
$ cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
==9416==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16
...
@ -205,6 +216,55 @@ $ cargo -Zbuild-std run --target x86_64-unknown-linux-gnu
#0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3
```
# ThreadSanitizer
ThreadSanitizer is a data race detection tool. It is supported on the following
targets:
* `x86_64-apple-darwin`
* `x86_64-unknown-linux-gnu`
To work correctly ThreadSanitizer needs to be "aware" of all synchronization
operations in a program. It generally achieves that through combination of
library interception (for example synchronization performed through
`pthread_mutex_lock` / `pthread_mutex_unlock`) and compile time instrumentation
(e.g. atomic operations). Using it without instrumenting all the program code
can lead to false positive reports.
ThreadSanitizer does not support atomic fences `std::sync::atomic::fence`,
nor synchronization performed using inline assembly code.
## Example
```rust
static mut A: usize = 0;
fn main() {
let t = std::thread::spawn(|| {
unsafe { A += 1 };
});
unsafe { A += 1 };
t.join().unwrap();
}
```
```shell
$ export RUSTFLAGS=-Zsanitizer=thread RUSTDOCFLAGS=-Zsanitizer=thread
$ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
==================
WARNING: ThreadSanitizer: data race (pid=10574)
Read of size 8 at 0x5632dfe3d030 by thread T1:
#0 example::main::_$u7b$$u7b$closure$u7d$$u7d$::h23f64b0b2f8c9484 ../src/main.rs:5:18 (example+0x86cec)
...
Previous write of size 8 at 0x5632dfe3d030 by main thread:
#0 example::main::h628ffc6626ed85b2 /.../src/main.rs:7:14 (example+0x868c8)
...
#11 main <null> (example+0x86a1a)
Location is global 'example::A::h43ac149ddf992709' of size 8 at 0x5632dfe3d030 (example+0x000000bd9030)
```
# Instrumentation of external dependencies and std
@ -231,6 +291,10 @@ In more practical terms when using cargo always remember to pass `--target`
flag, so that rustflags will not be applied to build scripts and procedural
macros.
# Symbolizing the Reports
Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PATH`.
# Additional Information
* [Sanitizers project page](https://github.com/google/sanitizers/wiki/)

View File

@ -87,7 +87,7 @@ Feedback on the design and usage is always appreciated!
The `Generator` trait in `std::ops` currently looks like:
```
```rust
# #![feature(arbitrary_self_types, generator_trait)]
# use std::ops::GeneratorState;
# use std::pin::Pin;
@ -107,7 +107,7 @@ point for executing the `Generator` itself.
The return value of `resume`, `GeneratorState`, looks like:
```
```rust
pub enum GeneratorState<Y, R> {
Yielded(Y),
Complete(R),

View File

@ -86,7 +86,7 @@ llvm_asm!("xor %eax, %eax" ::: "eax");
Input and output operands follow the same format: `:
"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
expressions must be mutable lvalues, or not yet assigned:
expressions must be mutable place, or not yet assigned:
```rust
# #![feature(llvm_asm)]

View File

@ -15,9 +15,6 @@ TEST_DIR = os.path.abspath(
os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))
TEMPLATE = """\
// FIXME: missing sysroot spans (#53081)
// ignore-i586-unknown-linux-gnu
// ignore-i586-unknown-linux-musl
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
{error_deriving}

View File

@ -2,7 +2,7 @@
#![stable(feature = "alloc_module", since = "1.28.0")]
use core::intrinsics::{min_align_of_val, size_of_val};
use core::intrinsics::{self, min_align_of_val, size_of_val};
use core::ptr::{NonNull, Unique};
use core::usize;
@ -165,11 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
#[unstable(feature = "allocator_api", issue = "32838")]
unsafe impl AllocRef for Global {
#[inline]
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
if layout.size() == 0 {
Ok((layout.dangling(), 0))
} else {
unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) }
fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr> {
unsafe {
let size = layout.size();
if size == 0 {
Ok(MemoryBlock { ptr: layout.dangling(), size: 0 })
} else {
let raw_ptr = match init {
AllocInit::Uninitialized => alloc(layout),
AllocInit::Zeroed => alloc_zeroed(layout),
};
let ptr = NonNull::new(raw_ptr).ok_or(AllocErr)?;
Ok(MemoryBlock { ptr, size })
}
}
}
@ -181,32 +189,71 @@ unsafe impl AllocRef for Global {
}
#[inline]
unsafe fn realloc(
unsafe fn grow(
&mut self,
ptr: NonNull<u8>,
layout: Layout,
new_size: usize,
) -> Result<(NonNull<u8>, usize), AllocErr> {
match (layout.size(), new_size) {
(0, 0) => Ok((layout.dangling(), 0)),
(0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
(_, 0) => {
self.dealloc(ptr, layout);
Ok((layout.dangling(), 0))
placement: ReallocPlacement,
init: AllocInit,
) -> Result<MemoryBlock, AllocErr> {
let size = layout.size();
debug_assert!(
new_size >= size,
"`new_size` must be greater than or equal to `memory.size()`"
);
if size == new_size {
return Ok(MemoryBlock { ptr, size });
}
match placement {
ReallocPlacement::InPlace => Err(AllocErr),
ReallocPlacement::MayMove if layout.size() == 0 => {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
self.alloc(new_layout, init)
}
ReallocPlacement::MayMove => {
// `realloc` probably checks for `new_size > size` or something similar.
intrinsics::assume(new_size > size);
let ptr = realloc(ptr.as_ptr(), layout, new_size);
let memory =
MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size };
init.init_offset(memory, size);
Ok(memory)
}
(_, _) => NonNull::new(realloc(ptr.as_ptr(), layout, new_size))
.ok_or(AllocErr)
.map(|p| (p, new_size)),
}
}
#[inline]
fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
if layout.size() == 0 {
Ok((layout.dangling(), 0))
} else {
unsafe {
NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
unsafe fn shrink(
&mut self,
ptr: NonNull<u8>,
layout: Layout,
new_size: usize,
placement: ReallocPlacement,
) -> Result<MemoryBlock, AllocErr> {
let size = layout.size();
debug_assert!(
new_size <= size,
"`new_size` must be smaller than or equal to `memory.size()`"
);
if size == new_size {
return Ok(MemoryBlock { ptr, size });
}
match placement {
ReallocPlacement::InPlace => Err(AllocErr),
ReallocPlacement::MayMove if new_size == 0 => {
self.dealloc(ptr, layout);
Ok(MemoryBlock { ptr: layout.dangling(), size: 0 })
}
ReallocPlacement::MayMove => {
// `realloc` probably checks for `new_size < size` or something similar.
intrinsics::assume(new_size < size);
let ptr = realloc(ptr.as_ptr(), layout, new_size);
Ok(MemoryBlock { ptr: NonNull::new(ptr).ok_or(AllocErr)?, size: new_size })
}
}
}
@ -218,14 +265,10 @@ unsafe impl AllocRef for Global {
#[lang = "exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
if size == 0 {
align as *mut u8
} else {
let layout = Layout::from_size_align_unchecked(size, align);
match Global.alloc(layout) {
Ok((ptr, _)) => ptr.as_ptr(),
Err(_) => handle_alloc_error(layout),
}
let layout = Layout::from_size_align_unchecked(size, align);
match Global.alloc(layout, AllocInit::Uninitialized) {
Ok(memory) => memory.ptr.as_ptr(),
Err(_) => handle_alloc_error(layout),
}
}
@ -239,11 +282,8 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
let size = size_of_val(ptr.as_ref());
let align = min_align_of_val(ptr.as_ref());
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
if size != 0 {
let layout = Layout::from_size_align_unchecked(size, align);
Global.dealloc(ptr.cast().into(), layout);
}
let layout = Layout::from_size_align_unchecked(size, align);
Global.dealloc(ptr.cast().into(), layout)
}
/// Abort on memory allocation error or failure.

View File

@ -8,16 +8,17 @@ use test::Bencher;
fn allocate_zeroed() {
unsafe {
let layout = Layout::from_size_align(1024, 1).unwrap();
let (ptr, _) =
Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout));
let memory = Global
.alloc(layout.clone(), AllocInit::Zeroed)
.unwrap_or_else(|_| handle_alloc_error(layout));
let mut i = ptr.cast::<u8>().as_ptr();
let mut i = memory.ptr.cast::<u8>().as_ptr();
let end = i.add(layout.size());
while i < end {
assert_eq!(*i, 0);
i = i.offset(1);
}
Global.dealloc(ptr, layout);
Global.dealloc(memory.ptr, layout);
}
}

View File

@ -62,6 +62,22 @@ pub fn clone_100_and_clear(b: &mut Bencher) {
b.iter(|| src.clone().clear())
}
#[bench]
pub fn clone_100_and_drain_all(b: &mut Bencher) {
let src = pos(100);
b.iter(|| src.clone().drain_filter(|_| true).count())
}
#[bench]
pub fn clone_100_and_drain_half(b: &mut Bencher) {
let src = pos(100);
b.iter(|| {
let mut set = src.clone();
assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 100 / 2);
assert_eq!(set.len(), 100 / 2);
})
}
#[bench]
pub fn clone_100_and_into_iter(b: &mut Bencher) {
let src = pos(100);
@ -115,6 +131,22 @@ pub fn clone_10k_and_clear(b: &mut Bencher) {
b.iter(|| src.clone().clear())
}
#[bench]
pub fn clone_10k_and_drain_all(b: &mut Bencher) {
let src = pos(10_000);
b.iter(|| src.clone().drain_filter(|_| true).count())
}
#[bench]
pub fn clone_10k_and_drain_half(b: &mut Bencher) {
let src = pos(10_000);
b.iter(|| {
let mut set = src.clone();
assert_eq!(set.drain_filter(|i| i % 2 == 0).count(), 10_000 / 2);
assert_eq!(set.len(), 10_000 / 2);
})
}
#[bench]
pub fn clone_10k_and_into_iter(b: &mut Bencher) {
let src = pos(10_000);

View File

@ -1,3 +1,4 @@
#![feature(btree_drain_filter)]
#![feature(map_first_last)]
#![feature(repr_simd)]
#![feature(test)]

View File

@ -143,10 +143,9 @@ use core::ops::{
};
use core::pin::Pin;
use core::ptr::{self, NonNull, Unique};
use core::slice;
use core::task::{Context, Poll};
use crate::alloc::{self, AllocRef, Global};
use crate::alloc::{self, AllocInit, AllocRef, Global};
use crate::raw_vec::RawVec;
use crate::str::from_boxed_utf8_unchecked;
use crate::vec::Vec;
@ -196,14 +195,12 @@ impl<T> Box<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
unsafe {
let ptr = if layout.size() == 0 {
NonNull::dangling()
} else {
Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast()
};
Box::from_raw(ptr.as_ptr())
}
let ptr = Global
.alloc(layout, AllocInit::Uninitialized)
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
.ptr
.cast();
unsafe { Box::from_raw(ptr.as_ptr()) }
}
/// Constructs a new `Box` with uninitialized contents, with the memory
@ -226,11 +223,13 @@ impl<T> Box<T> {
/// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
unsafe {
let mut uninit = Self::new_uninit();
ptr::write_bytes::<T>(uninit.as_mut_ptr(), 0, 1);
uninit
}
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
let ptr = Global
.alloc(layout, AllocInit::Zeroed)
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
.ptr
.cast();
unsafe { Box::from_raw(ptr.as_ptr()) }
}
/// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then
@ -265,15 +264,7 @@ impl<T> Box<[T]> {
/// ```
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
unsafe {
let ptr = if layout.size() == 0 {
NonNull::dangling()
} else {
Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast()
};
Box::from_raw(slice::from_raw_parts_mut(ptr.as_ptr(), len))
}
unsafe { RawVec::with_capacity(len).into_box(len) }
}
}
@ -778,7 +769,7 @@ impl<T: Copy> From<&[T]> for Box<[T]> {
let buf = RawVec::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(slice.as_ptr(), buf.ptr(), len);
buf.into_box()
buf.into_box(slice.len()).assume_init()
}
}
}

View File

@ -1256,6 +1256,48 @@ impl<K: Ord, V> BTreeMap<K, V> {
right
}
/// Creates an iterator which uses a closure to determine if an element should be removed.
///
/// If the closure returns true, the element is removed from the map and yielded.
/// If the closure returns false, or panics, the element remains in the map and will not be
/// yielded.
///
/// Note that `drain_filter` lets you mutate every value in the filter closure, regardless of
/// whether you choose to keep or remove it.
///
/// If the iterator is only partially consumed or not consumed at all, each of the remaining
/// elements will still be subjected to the closure and removed and dropped if it returns true.
///
/// It is unspecified how many more elements will be subjected to the closure
/// if a panic occurs in the closure, or a panic occurs while dropping an element,
/// or if the `DrainFilter` value is leaked.
///
/// # Examples
///
/// Splitting a map into even and odd keys, reusing the original map:
///
/// ```
/// #![feature(btree_drain_filter)]
/// use std::collections::BTreeMap;
///
/// let mut map: BTreeMap<i32, i32> = (0..8).map(|x| (x, x)).collect();
/// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect();
/// let odds = map;
/// assert_eq!(evens.keys().copied().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
/// assert_eq!(odds.keys().copied().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
/// ```
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, K, V, F>
where
F: FnMut(&K, &mut V) -> bool,
{
DrainFilter { pred, inner: self.drain_filter_inner() }
}
pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
let front = self.root.as_mut().map(|r| r.as_mut().first_leaf_edge());
DrainFilterInner { length: &mut self.length, cur_leaf_edge: front }
}
/// Calculates the number of elements if it is incorrect.
fn recalc_length(&mut self) {
fn dfs<'a, K, V>(node: NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>) -> usize
@ -1653,6 +1695,124 @@ impl<K, V> Clone for Values<'_, K, V> {
}
}
/// An iterator produced by calling `drain_filter` on BTreeMap.
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub struct DrainFilter<'a, K, V, F>
where
K: 'a + Ord, // This Ord bound should be removed before stabilization.
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
{
pred: F,
inner: DrainFilterInner<'a, K, V>,
}
pub(super) struct DrainFilterInner<'a, K, V>
where
K: 'a + Ord,
V: 'a,
{
length: &'a mut usize,
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> Drop for DrainFilter<'a, K, V, F>
where
K: 'a + Ord,
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
{
fn drop(&mut self) {
self.for_each(drop);
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> fmt::Debug for DrainFilter<'a, K, V, F>
where
K: 'a + fmt::Debug + Ord,
V: 'a + fmt::Debug,
F: 'a + FnMut(&K, &mut V) -> bool,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek()).finish()
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, K, V, F> Iterator for DrainFilter<'a, K, V, F>
where
K: 'a + Ord,
V: 'a,
F: 'a + FnMut(&K, &mut V) -> bool,
{
type Item = (K, V);
fn next(&mut self) -> Option<(K, V)> {
self.inner.next(&mut self.pred)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl<'a, K, V> DrainFilterInner<'a, K, V>
where
K: 'a + Ord,
V: 'a,
{
/// Allow Debug implementations to predict the next element.
pub(super) fn peek(&self) -> Option<(&K, &V)> {
let edge = self.cur_leaf_edge.as_ref()?;
edge.reborrow().next_kv().ok().map(|kv| kv.into_kv())
}
unsafe fn next_kv(
&mut self,
) -> Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>> {
let edge = self.cur_leaf_edge.as_ref()?;
ptr::read(edge).next_kv().ok()
}
/// Implementation of a typical `DrainFilter::next` method, given the predicate.
pub(super) fn next<F>(&mut self, pred: &mut F) -> Option<(K, V)>
where
F: FnMut(&K, &mut V) -> bool,
{
while let Some(kv) = unsafe { self.next_kv() } {
let (k, v) = unsafe { ptr::read(&kv) }.into_kv_mut();
if pred(k, v) {
*self.length -= 1;
let (k, v, leaf_edge_location) = kv.remove_kv_tracking();
// `remove_kv_tracking` has either preserved or invalidated `self.cur_leaf_edge`
if let Some(node) = leaf_edge_location {
match search::search_tree(node, &k) {
search::SearchResult::Found(_) => unreachable!(),
search::SearchResult::GoDown(leaf) => self.cur_leaf_edge = Some(leaf),
}
};
return Some((k, v));
}
self.cur_leaf_edge = Some(kv.next_leaf_edge());
}
None
}
/// Implementation of a typical `DrainFilter::size_hint` method.
pub(super) fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(*self.length))
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<K, V, F> FusedIterator for DrainFilter<'_, K, V, F>
where
K: Ord,
F: FnMut(&K, &mut V) -> bool,
{
}
#[stable(feature = "btree_range", since = "1.17.0")]
impl<'a, K, V> Iterator for Range<'a, K, V> {
type Item = (&'a K, &'a V);
@ -2531,12 +2691,31 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
fn remove_kv(self) -> (K, V) {
*self.length -= 1;
let (small_leaf, old_key, old_val) = match self.handle.force() {
let (old_key, old_val, _) = self.handle.remove_kv_tracking();
(old_key, old_val)
}
}
impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
/// Removes a key/value-pair from the map, and returns that pair, as well as
/// the whereabouts of the leaf edge corresponding to that former pair:
/// if None is returned, the leaf edge is still the left leaf edge of the KV handle;
/// if a node is returned, it heads the subtree where the leaf edge may be found.
fn remove_kv_tracking(
self,
) -> (K, V, Option<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>>) {
let mut levels_down_handled: isize;
let (small_leaf, old_key, old_val) = match self.force() {
Leaf(leaf) => {
levels_down_handled = 1; // handled at same level, but affects only the right side
let (hole, old_key, old_val) = leaf.remove();
(hole.into_node(), old_key, old_val)
}
Internal(mut internal) => {
// Replace the location freed in the internal node with the next KV,
// and remove that next KV from its leaf.
levels_down_handled = unsafe { ptr::read(&internal).into_node().height() } as isize;
let key_loc = internal.kv_mut().0 as *mut K;
let val_loc = internal.kv_mut().1 as *mut V;
@ -2556,27 +2735,39 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
let mut cur_node = small_leaf.forget_type();
while cur_node.len() < node::MIN_LEN {
match handle_underfull_node(cur_node) {
AtRoot => break,
AtRoot(root) => {
cur_node = root;
break;
}
EmptyParent(_) => unreachable!(),
Merged(parent) => {
levels_down_handled -= 1;
if parent.len() == 0 {
// We must be at the root
parent.into_root_mut().pop_level();
let root = parent.into_root_mut();
root.pop_level();
cur_node = root.as_mut();
break;
} else {
cur_node = parent.forget_type();
}
}
Stole(_) => break,
Stole(internal_node) => {
levels_down_handled -= 1;
cur_node = internal_node.forget_type();
// This internal node might be underfull, but only if it's the root.
break;
}
}
}
(old_key, old_val)
let leaf_edge_location = if levels_down_handled > 0 { None } else { Some(cur_node) };
(old_key, old_val, leaf_edge_location)
}
}
enum UnderflowResult<'a, K, V> {
AtRoot,
AtRoot(NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>),
EmptyParent(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
Merged(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
Stole(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
@ -2585,10 +2776,9 @@ enum UnderflowResult<'a, K, V> {
fn handle_underfull_node<K, V>(
node: NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal>,
) -> UnderflowResult<'_, K, V> {
let parent = if let Ok(parent) = node.ascend() {
parent
} else {
return AtRoot;
let parent = match node.ascend() {
Ok(parent) => parent,
Err(root) => return AtRoot(root),
};
let (is_left, mut handle) = match parent.left_kv() {

View File

@ -1142,7 +1142,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
(*left_node.as_leaf_mut()).len += right_len as u16 + 1;
if self.node.height > 1 {
let layout = if self.node.height > 1 {
ptr::copy_nonoverlapping(
right_node.cast_unchecked().as_internal().edges.as_ptr(),
left_node
@ -1159,10 +1159,11 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
.correct_parent_link();
}
Global.dealloc(right_node.node.cast(), Layout::new::<InternalNode<K, V>>());
Layout::new::<InternalNode<K, V>>()
} else {
Global.dealloc(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
}
Layout::new::<LeafNode<K, V>>()
};
Global.dealloc(right_node.node.cast(), layout);
Handle::new_edge(self.node, self.idx)
}

View File

@ -8,8 +8,8 @@ use core::fmt::{self, Debug};
use core::iter::{FromIterator, FusedIterator, Peekable};
use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub};
use super::map::{BTreeMap, Keys};
use super::Recover;
use crate::collections::btree_map::{self, BTreeMap, Keys};
// FIXME(conventions): implement bounded iterators
@ -102,7 +102,7 @@ impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IntoIter<T> {
iter: btree_map::IntoIter<T, ()>,
iter: super::map::IntoIter<T, ()>,
}
/// An iterator over a sub-range of items in a `BTreeSet`.
@ -115,7 +115,7 @@ pub struct IntoIter<T> {
#[derive(Debug)]
#[stable(feature = "btree_range", since = "1.17.0")]
pub struct Range<'a, T: 'a> {
iter: btree_map::Range<'a, T, ()>,
iter: super::map::Range<'a, T, ()>,
}
/// Core of SymmetricDifference and Union.
@ -944,6 +944,41 @@ impl<T: Ord> BTreeSet<T> {
{
BTreeSet { map: self.map.split_off(key) }
}
/// Creates an iterator which uses a closure to determine if a value should be removed.
///
/// If the closure returns true, then the value is removed and yielded.
/// If the closure returns false, the value will remain in the list and will not be yielded
/// by the iterator.
///
/// If the iterator is only partially consumed or not consumed at all, each of the remaining
/// values will still be subjected to the closure and removed and dropped if it returns true.
///
/// It is unspecified how many more values will be subjected to the closure
/// if a panic occurs in the closure, or if a panic occurs while dropping a value, or if the
/// `DrainFilter` itself is leaked.
///
/// # Examples
///
/// Splitting a set into even and odd values, reusing the original set:
///
/// ```
/// #![feature(btree_drain_filter)]
/// use std::collections::BTreeSet;
///
/// let mut set: BTreeSet<i32> = (0..8).collect();
/// let evens: BTreeSet<_> = set.drain_filter(|v| v % 2 == 0).collect();
/// let odds = set;
/// assert_eq!(evens.into_iter().collect::<Vec<_>>(), vec![0, 2, 4, 6]);
/// assert_eq!(odds.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
/// ```
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, F>
where
F: 'a + FnMut(&T) -> bool,
{
DrainFilter { pred, inner: self.map.drain_filter_inner() }
}
}
impl<T> BTreeSet<T> {
@ -1055,6 +1090,66 @@ impl<'a, T> IntoIterator for &'a BTreeSet<T> {
}
}
/// An iterator produced by calling `drain_filter` on BTreeSet.
#[unstable(feature = "btree_drain_filter", issue = "70530")]
pub struct DrainFilter<'a, T, F>
where
T: 'a + Ord,
F: 'a + FnMut(&T) -> bool,
{
pred: F,
inner: super::map::DrainFilterInner<'a, T, ()>,
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> Drop for DrainFilter<'a, T, F>
where
T: 'a + Ord,
F: 'a + FnMut(&T) -> bool,
{
fn drop(&mut self) {
self.for_each(drop);
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> fmt::Debug for DrainFilter<'a, T, F>
where
T: 'a + Ord + fmt::Debug,
F: 'a + FnMut(&T) -> bool,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("DrainFilter").field(&self.inner.peek().map(|(k, _)| k)).finish()
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, 'f, T, F> Iterator for DrainFilter<'a, T, F>
where
T: 'a + Ord,
F: 'a + 'f + FnMut(&T) -> bool,
{
type Item = T;
fn next(&mut self) -> Option<T> {
let pred = &mut self.pred;
let mut mapped_pred = |k: &T, _v: &mut ()| pred(k);
self.inner.next(&mut mapped_pred).map(|(k, _)| k)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
impl<'a, T, F> FusedIterator for DrainFilter<'a, T, F>
where
T: 'a + Ord,
F: 'a + FnMut(&T) -> bool,
{
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Extend<T> for BTreeSet<T> {
#[inline]

View File

@ -959,6 +959,9 @@ impl<T> VecDeque<T> {
/// Returns a pair of slices which contain, in order, the contents of the
/// `VecDeque`.
///
/// If [`make_contiguous`](#method.make_contiguous) was previously called, all elements
/// of the `VecDeque` will be in the first slice and the second slice will be empty.
///
/// # Examples
///
/// ```
@ -989,6 +992,9 @@ impl<T> VecDeque<T> {
/// Returns a pair of slices which contain, in order, the contents of the
/// `VecDeque`.
///
/// If [`make_contiguous`](#method.make_contiguous) was previously called, all elements
/// of the `VecDeque` will be in the first slice and the second slice will be empty.
///
/// # Examples
///
/// ```
@ -2044,6 +2050,148 @@ impl<T> VecDeque<T> {
}
}
/// Rearranges the internal storage of this deque so it is one contiguous slice, which is then returned.
///
/// This method does not allocate and does not change the order of the inserted elements.
/// As it returns a mutable slice, this can be used to sort or binary search a deque.
///
/// Once the internal storage is contiguous, the [`as_slices`](#method.as_slices) and
/// [`as_mut_slices`](#method.as_mut_slices) methods will return the entire contents of the
/// `VecDeque` in a single slice.
///
/// # Examples
///
/// Sorting the content of a deque.
///
/// ```
/// #![feature(deque_make_contiguous)]
///
/// use std::collections::VecDeque;
///
/// let mut buf = VecDeque::with_capacity(15);
///
/// buf.push_back(2);
/// buf.push_back(1);
/// buf.push_front(3);
///
/// // sorting the deque
/// buf.make_contiguous().sort();
/// assert_eq!(buf.as_slices(), (&[1, 2, 3] as &[_], &[] as &[_]));
///
/// // sorting it in reverse order
/// buf.make_contiguous().sort_by(|a, b| b.cmp(a));
/// assert_eq!(buf.as_slices(), (&[3, 2, 1] as &[_], &[] as &[_]));
/// ```
///
/// Getting immutable access to the contiguous slice.
///
/// ```rust
/// #![feature(deque_make_contiguous)]
///
/// use std::collections::VecDeque;
///
/// let mut buf = VecDeque::new();
///
/// buf.push_back(2);
/// buf.push_back(1);
/// buf.push_front(3);
///
/// buf.make_contiguous();
/// if let (slice, &[]) = buf.as_slices() {
/// // we can now be sure that `slice` contains all elements of the deque,
/// // while still having immutable access to `buf`.
/// assert_eq!(buf.len(), slice.len());
/// assert_eq!(slice, &[3, 2, 1] as &[_]);
/// }
/// ```
#[unstable(feature = "deque_make_contiguous", issue = "none")]
pub fn make_contiguous(&mut self) -> &mut [T] {
if self.is_contiguous() {
let tail = self.tail;
let head = self.head;
return unsafe { &mut self.buffer_as_mut_slice()[tail..head] };
}
let buf = self.buf.ptr();
let cap = self.cap();
let len = self.len();
let free = self.tail - self.head;
let tail_len = cap - self.tail;
if free >= tail_len {
// there is enough free space to copy the tail in one go,
// this means that we first shift the head backwards, and then
// copy the tail to the correct position.
//
// from: DEFGH....ABC
// to: ABCDEFGH....
unsafe {
ptr::copy(buf, buf.add(tail_len), self.head);
// ...DEFGH.ABC
ptr::copy_nonoverlapping(buf.add(self.tail), buf, tail_len);
// ABCDEFGH....
self.tail = 0;
self.head = len;
}
} else if free >= self.head {
// there is enough free space to copy the head in one go,
// this means that we first shift the tail forwards, and then
// copy the head to the correct position.
//
// from: FGH....ABCDE
// to: ...ABCDEFGH.
unsafe {
ptr::copy(buf.add(self.tail), buf.add(self.head), tail_len);
// FGHABCDE....
ptr::copy_nonoverlapping(buf, buf.add(self.head + tail_len), self.head);
// ...ABCDEFGH.
self.tail = self.head;
self.head = self.tail + len;
}
} else {
// free is smaller than both head and tail,
// this means we have to slowly "swap" the tail and the head.
//
// from: EFGHI...ABCD or HIJK.ABCDEFG
// to: ABCDEFGHI... or ABCDEFGHIJK.
let mut left_edge: usize = 0;
let mut right_edge: usize = self.tail;
unsafe {
// The general problem looks like this
// GHIJKLM...ABCDEF - before any swaps
// ABCDEFM...GHIJKL - after 1 pass of swaps
// ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
// - then restart the algorithm with a new (smaller) store
// Sometimes the temp store is reached when the right edge is at the end
// of the buffer - this means we've hit the right order with fewer swaps!
// E.g
// EF..ABCD
// ABCDEF.. - after four only swaps we've finished
while left_edge < len && right_edge != cap {
let mut right_offset = 0;
for i in left_edge..right_edge {
right_offset = (i - left_edge) % (cap - right_edge);
let src: isize = (right_edge + right_offset) as isize;
ptr::swap(buf.add(i), buf.offset(src));
}
let n_ops = right_edge - left_edge;
left_edge += n_ops;
right_edge += right_offset + 1;
}
self.tail = 0;
self.head = len;
}
}
let tail = self.tail;
let head = self.head;
unsafe { &mut self.buffer_as_mut_slice()[tail..head] }
}
/// Rotates the double-ended queue `mid` places to the left.
///
/// Equivalently,
@ -2803,63 +2951,16 @@ impl<T> From<VecDeque<T>> for Vec<T> {
/// assert_eq!(vec, [8, 9, 1, 2, 3, 4]);
/// assert_eq!(vec.as_ptr(), ptr);
/// ```
fn from(other: VecDeque<T>) -> Self {
fn from(mut other: VecDeque<T>) -> Self {
other.make_contiguous();
unsafe {
let buf = other.buf.ptr();
let len = other.len();
let tail = other.tail;
let head = other.head;
let cap = other.cap();
// Need to move the ring to the front of the buffer, as vec will expect this.
if other.is_contiguous() {
ptr::copy(buf.add(tail), buf, len);
} else {
if (tail - head) >= cmp::min(cap - tail, head) {
// There is enough free space in the centre for the shortest block so we can
// do this in at most three copy moves.
if (cap - tail) > head {
// right hand block is the long one; move that enough for the left
ptr::copy(buf.add(tail), buf.add(tail - head), cap - tail);
// copy left in the end
ptr::copy(buf, buf.add(cap - head), head);
// shift the new thing to the start
ptr::copy(buf.add(tail - head), buf, len);
} else {
// left hand block is the long one, we can do it in two!
ptr::copy(buf, buf.add(cap - tail), head);
ptr::copy(buf.add(tail), buf, cap - tail);
}
} else {
// Need to use N swaps to move the ring
// We can use the space at the end of the ring as a temp store
let mut left_edge: usize = 0;
let mut right_edge: usize = tail;
// The general problem looks like this
// GHIJKLM...ABCDEF - before any swaps
// ABCDEFM...GHIJKL - after 1 pass of swaps
// ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
// - then restart the algorithm with a new (smaller) store
// Sometimes the temp store is reached when the right edge is at the end
// of the buffer - this means we've hit the right order with fewer swaps!
// E.g
// EF..ABCD
// ABCDEF.. - after four only swaps we've finished
while left_edge < len && right_edge != cap {
let mut right_offset = 0;
for i in left_edge..right_edge {
right_offset = (i - left_edge) % (cap - right_edge);
let src: isize = (right_edge + right_offset) as isize;
ptr::swap(buf.add(i), buf.offset(src));
}
let n_ops = right_edge - left_edge;
left_edge += n_ops;
right_edge += right_offset + 1;
}
}
if other.head != 0 {
ptr::copy(buf.add(other.tail), buf, len);
}
let out = Vec::from_raw_parts(buf, len, cap);
mem::forget(other);

View File

@ -1,6 +1,6 @@
use super::*;
use ::test;
use test;
#[bench]
#[cfg_attr(miri, ignore)] // Miri does not support benchmarks
@ -130,6 +130,87 @@ fn test_insert() {
}
}
#[test]
fn make_contiguous_big_tail() {
let mut tester = VecDeque::with_capacity(15);
for i in 0..3 {
tester.push_back(i);
}
for i in 3..10 {
tester.push_front(i);
}
// 012......9876543
assert_eq!(tester.capacity(), 15);
assert_eq!((&[9, 8, 7, 6, 5, 4, 3] as &[_], &[0, 1, 2] as &[_]), tester.as_slices());
let expected_start = tester.head;
tester.make_contiguous();
assert_eq!(tester.tail, expected_start);
assert_eq!((&[9, 8, 7, 6, 5, 4, 3, 0, 1, 2] as &[_], &[] as &[_]), tester.as_slices());
}
#[test]
fn make_contiguous_big_head() {
let mut tester = VecDeque::with_capacity(15);
for i in 0..8 {
tester.push_back(i);
}
for i in 8..10 {
tester.push_front(i);
}
// 01234567......98
let expected_start = 0;
tester.make_contiguous();
assert_eq!(tester.tail, expected_start);
assert_eq!((&[9, 8, 0, 1, 2, 3, 4, 5, 6, 7] as &[_], &[] as &[_]), tester.as_slices());
}
#[test]
fn make_contiguous_small_free() {
let mut tester = VecDeque::with_capacity(15);
for i in 'A' as u8..'I' as u8 {
tester.push_back(i as char);
}
for i in 'I' as u8..'N' as u8 {
tester.push_front(i as char);
}
// ABCDEFGH...MLKJI
let expected_start = 0;
tester.make_contiguous();
assert_eq!(tester.tail, expected_start);
assert_eq!(
(&['M', 'L', 'K', 'J', 'I', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] as &[_], &[] as &[_]),
tester.as_slices()
);
tester.clear();
for i in 'I' as u8..'N' as u8 {
tester.push_back(i as char);
}
for i in 'A' as u8..'I' as u8 {
tester.push_front(i as char);
}
// IJKLM...HGFEDCBA
let expected_start = 0;
tester.make_contiguous();
assert_eq!(tester.tail, expected_start);
assert_eq!(
(&['H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', 'I', 'J', 'K', 'L', 'M'] as &[_], &[] as &[_]),
tester.as_slices()
);
}
#[test]
fn test_remove() {
// This test checks that every single combination of tail position, length, and

View File

@ -100,6 +100,7 @@
#![feature(lang_items)]
#![feature(libc)]
#![cfg_attr(not(bootstrap), feature(negative_impls))]
#![feature(new_uninit)]
#![feature(nll)]
#![feature(optin_builtin_traits)]
#![feature(pattern)]

View File

@ -36,6 +36,9 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
);
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
);
@ -51,6 +54,9 @@ macro_rules! vec {
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
() => (
$crate::vec::Vec::new()
);
($elem:expr; $n:expr) => (
$crate::vec::from_elem($elem, $n)
);

View File

@ -1,13 +1,19 @@
#![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")]
#![doc(hidden)]
use core::alloc::MemoryBlock;
use core::cmp;
use core::mem;
use core::mem::{self, MaybeUninit};
use core::ops::Drop;
use core::ptr::{self, NonNull, Unique};
use core::ptr::{NonNull, Unique};
use core::slice;
use crate::alloc::{handle_alloc_error, AllocErr, AllocRef, Global, Layout};
use crate::alloc::{
handle_alloc_error, AllocErr,
AllocInit::{self, *},
AllocRef, Global, Layout,
ReallocPlacement::{self, *},
};
use crate::boxed::Box;
use crate::collections::TryReserveError::{self, *};
@ -21,81 +27,26 @@ mod tests;
///
/// * Produces `Unique::empty()` on zero-sized types.
/// * Produces `Unique::empty()` on zero-length allocations.
/// * Avoids freeing `Unique::empty()`.
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics).
/// * Guards against 32-bit systems allocating more than isize::MAX bytes.
/// * Guards against overflowing your length.
/// * Aborts on OOM or calls `handle_alloc_error` as applicable.
/// * Avoids freeing `Unique::empty()`.
/// * Calls `handle_alloc_error` for fallible allocations.
/// * Contains a `ptr::Unique` and thus endows the user with all related benefits.
/// * Uses the excess returned from the allocator to use the largest available capacity.
///
/// This type does not in anyway inspect the memory that it manages. When dropped it *will*
/// free its memory, but it *won't* try to drop its contents. It is up to the user of `RawVec`
/// to handle the actual things *stored* inside of a `RawVec`.
///
/// Note that a `RawVec` always forces its capacity to be `usize::MAX` for zero-sized types.
/// This enables you to use capacity-growing logic catch the overflows in your length
/// that might occur with zero-sized types.
///
/// The above means that you need to be careful when round-tripping this type with a
/// `Box<[T]>`, since `capacity()` won't yield the length. However, `with_capacity`,
/// `shrink_to_fit`, and `from_box` will actually set `RawVec`'s private capacity
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
/// Note that the excess of a zero-sized types is always infinite, so `capacity()` always returns
/// `usize::MAX`. This means that you need to be careful when round-tripping this type with a
/// `Box<[T]>`, since `capacity()` won't yield the length.
#[allow(missing_debug_implementations)]
pub struct RawVec<T, A: AllocRef = Global> {
ptr: Unique<T>,
cap: usize,
a: A,
}
impl<T, A: AllocRef> RawVec<T, A> {
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
pub const fn new_in(a: A) -> Self {
let cap = if mem::size_of::<T>() == 0 { core::usize::MAX } else { 0 };
// `Unique::empty()` doubles as "unallocated" and "zero-sized allocation".
RawVec { ptr: Unique::empty(), cap, a }
}
/// Like `with_capacity`, but parameterized over the choice of
/// allocator for the returned `RawVec`.
#[inline]
pub fn with_capacity_in(capacity: usize, a: A) -> Self {
RawVec::allocate_in(capacity, false, a)
}
/// Like `with_capacity_zeroed`, but parameterized over the choice
/// of allocator for the returned `RawVec`.
#[inline]
pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self {
RawVec::allocate_in(capacity, true, a)
}
fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self {
let elem_size = mem::size_of::<T>();
let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
// Handles ZSTs and `capacity == 0` alike.
let ptr = if alloc_size == 0 {
NonNull::<T>::dangling()
} else {
let align = mem::align_of::<T>();
let layout = Layout::from_size_align(alloc_size, align).unwrap();
let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
match result {
Ok((ptr, size)) => {
capacity = size / elem_size;
ptr.cast()
}
Err(_) => handle_alloc_error(layout),
}
};
RawVec { ptr: ptr.into(), cap: capacity, a }
}
alloc: A,
}
impl<T> RawVec<T, Global> {
@ -138,39 +89,26 @@ impl<T> RawVec<T, Global> {
/// Aborts on OOM.
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
RawVec::allocate_in(capacity, false, Global)
Self::with_capacity_in(capacity, Global)
}
/// Like `with_capacity`, but guarantees the buffer is zeroed.
#[inline]
pub fn with_capacity_zeroed(capacity: usize) -> Self {
RawVec::allocate_in(capacity, true, Global)
Self::with_capacity_zeroed_in(capacity, Global)
}
}
impl<T, A: AllocRef> RawVec<T, A> {
/// Reconstitutes a `RawVec` from a pointer, capacity, and allocator.
///
/// # Undefined Behavior
///
/// The `ptr` must be allocated (via the given allocator `a`), and with the given `capacity`.
/// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
/// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed.
pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self {
RawVec { ptr: Unique::new_unchecked(ptr), cap: capacity, a }
}
}
impl<T> RawVec<T, Global> {
/// Reconstitutes a `RawVec` from a pointer and capacity.
///
/// # Undefined Behavior
/// # Safety
///
/// The `ptr` must be allocated (on the system heap), and with the given `capacity`.
/// The `capacity` cannot exceed `isize::MAX` (only a concern on 32-bit systems).
/// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit
/// systems). ZST vectors may have a capacity up to `usize::MAX`.
/// If the `ptr` and `capacity` come from a `RawVec`, then this is guaranteed.
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self {
RawVec { ptr: Unique::new_unchecked(ptr), cap: capacity, a: Global }
Self::from_raw_parts_in(ptr, capacity, Global)
}
/// Converts a `Box<[T]>` into a `RawVec<T>`.
@ -184,6 +122,56 @@ impl<T> RawVec<T, Global> {
}
impl<T, A: AllocRef> RawVec<T, A> {
/// Like `new`, but parameterized over the choice of allocator for
/// the returned `RawVec`.
pub const fn new_in(alloc: A) -> Self {
// `cap: 0` means "unallocated". zero-sized types are ignored.
Self { ptr: Unique::empty(), cap: 0, alloc }
}
/// Like `with_capacity`, but parameterized over the choice of
/// allocator for the returned `RawVec`.
#[inline]
pub fn with_capacity_in(capacity: usize, alloc: A) -> Self {
Self::allocate_in(capacity, Uninitialized, alloc)
}
/// Like `with_capacity_zeroed`, but parameterized over the choice
/// of allocator for the returned `RawVec`.
#[inline]
pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self {
Self::allocate_in(capacity, Zeroed, alloc)
}
fn allocate_in(capacity: usize, init: AllocInit, mut alloc: A) -> Self {
if mem::size_of::<T>() == 0 {
Self::new_in(alloc)
} else {
let layout = Layout::array::<T>(capacity).unwrap_or_else(|_| capacity_overflow());
alloc_guard(layout.size()).unwrap_or_else(|_| capacity_overflow());
let memory = alloc.alloc(layout, init).unwrap_or_else(|_| handle_alloc_error(layout));
Self {
ptr: memory.ptr.cast().into(),
cap: Self::capacity_from_bytes(memory.size),
alloc,
}
}
}
/// Reconstitutes a `RawVec` from a pointer, capacity, and allocator.
///
/// # Safety
///
/// The `ptr` must be allocated (via the given allocator `a`), and with the given `capacity`.
/// The `capacity` cannot exceed `isize::MAX` for sized types. (only a concern on 32-bit
/// systems). ZST vectors may have a capacity up to `usize::MAX`.
/// If the `ptr` and `capacity` come from a `RawVec` created via `a`, then this is guaranteed.
#[inline]
pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self {
Self { ptr: Unique::new_unchecked(ptr), cap: capacity, alloc: a }
}
/// Gets a raw pointer to the start of the allocation. Note that this is
/// `Unique::empty()` if `capacity == 0` or `T` is zero-sized. In the former case, you must
/// be careful.
@ -196,21 +184,21 @@ impl<T, A: AllocRef> RawVec<T, A> {
/// This will always be `usize::MAX` if `T` is zero-sized.
#[inline(always)]
pub fn capacity(&self) -> usize {
if mem::size_of::<T>() == 0 { !0 } else { self.cap }
if mem::size_of::<T>() == 0 { usize::MAX } else { self.cap }
}
/// Returns a shared reference to the allocator backing this `RawVec`.
pub fn alloc(&self) -> &A {
&self.a
&self.alloc
}
/// Returns a mutable reference to the allocator backing this `RawVec`.
pub fn alloc_mut(&mut self) -> &mut A {
&mut self.a
&mut self.alloc
}
fn current_layout(&self) -> Option<Layout> {
if self.cap == 0 {
fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
if mem::size_of::<T>() == 0 || self.cap == 0 {
None
} else {
// We have an allocated chunk of memory, so we can bypass runtime
@ -218,7 +206,8 @@ impl<T, A: AllocRef> RawVec<T, A> {
unsafe {
let align = mem::align_of::<T>();
let size = mem::size_of::<T>() * self.cap;
Some(Layout::from_size_align_unchecked(size, align))
let layout = Layout::from_size_align_unchecked(size, align);
Some((self.ptr.cast().into(), layout))
}
}
}
@ -274,50 +263,10 @@ impl<T, A: AllocRef> RawVec<T, A> {
#[inline(never)]
#[cold]
pub fn double(&mut self) {
unsafe {
let elem_size = mem::size_of::<T>();
// Since we set the capacity to `usize::MAX` when `elem_size` is
// 0, getting to here necessarily means the `RawVec` is overfull.
assert!(elem_size != 0, "capacity overflow");
let (ptr, new_cap) = match self.current_layout() {
Some(cur) => {
// Since we guarantee that we never allocate more than
// `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as
// a precondition, so this can't overflow. Additionally the
// alignment will never be too large as to "not be
// satisfiable", so `Layout::from_size_align` will always
// return `Some`.
//
// TL;DR, we bypass runtime checks due to dynamic assertions
// in this module, allowing us to use
// `from_size_align_unchecked`.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size);
match ptr_res {
Ok((ptr, new_size)) => (ptr, new_size / elem_size),
Err(_) => handle_alloc_error(Layout::from_size_align_unchecked(
new_size,
cur.align(),
)),
}
}
None => {
// Skip to 4 because tiny `Vec`'s are dumb; but not if that
// would cause overflow.
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
let layout = Layout::array::<T>(new_cap).unwrap();
match self.a.alloc(layout) {
Ok((ptr, new_size)) => (ptr, new_size / elem_size),
Err(_) => handle_alloc_error(layout),
}
}
};
self.ptr = ptr.cast().into();
self.cap = new_cap;
match self.grow(Double, MayMove, Uninitialized) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocError { layout, .. }) => handle_alloc_error(layout),
Ok(()) => { /* yay */ }
}
}
@ -336,99 +285,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
#[inline(never)]
#[cold]
pub fn double_in_place(&mut self) -> bool {
unsafe {
let elem_size = mem::size_of::<T>();
let old_layout = match self.current_layout() {
Some(layout) => layout,
None => return false, // nothing to double
};
// Since we set the capacity to `usize::MAX` when `elem_size` is
// 0, getting to here necessarily means the `RawVec` is overfull.
assert!(elem_size != 0, "capacity overflow");
// Since we guarantee that we never allocate more than `isize::MAX`
// bytes, `elem_size * self.cap <= isize::MAX` as a precondition, so
// this can't overflow.
//
// Similarly to with `double` above, we can go straight to
// `Layout::from_size_align_unchecked` as we know this won't
// overflow and the alignment is sufficiently small.
let new_cap = 2 * self.cap;
let new_size = new_cap * elem_size;
alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(NonNull::from(self.ptr).cast(), old_layout, new_size) {
Ok(_) => {
// We can't directly divide `size`.
self.cap = new_cap;
true
}
Err(_) => false,
}
}
}
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
pub fn try_reserve_exact(
&mut self,
used_capacity: usize,
needed_extra_capacity: usize,
) -> Result<(), TryReserveError> {
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact)
}
/// Ensures that the buffer contains at least enough space to hold
/// `used_capacity + needed_extra_capacity` elements. If it doesn't already,
/// will reallocate the minimum possible amount of memory necessary.
/// Generally this will be exactly the amount of memory necessary,
/// but in principle the allocator is free to give back more than
/// we asked for.
///
/// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate
/// the requested space. This is not really unsafe, but the unsafe
/// code *you* write that relies on the behavior of this function may break.
///
/// # Panics
///
/// * Panics if the requested capacity exceeds `usize::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM.
pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocError { .. }) => unreachable!(),
Ok(()) => { /* yay */ }
}
}
/// Calculates the buffer's new size given that it'll hold `used_capacity +
/// needed_extra_capacity` elements. This logic is used in amortized reserve methods.
/// Returns `(new_capacity, new_alloc_size)`.
fn amortized_new_size(
&self,
used_capacity: usize,
needed_extra_capacity: usize,
) -> Result<usize, TryReserveError> {
// Nothing we can really do about these checks, sadly.
let required_cap =
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?;
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
let double_cap = self.cap * 2;
// `double_cap` guarantees exponential growth.
Ok(cmp::max(double_cap, required_cap))
}
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
pub fn try_reserve(
&mut self,
used_capacity: usize,
needed_extra_capacity: usize,
) -> Result<(), TryReserveError> {
self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized)
self.grow(Double, InPlace, Uninitialized).is_ok()
}
/// Ensures that the buffer contains at least enough space to hold
@ -484,12 +341,26 @@ impl<T, A: AllocRef> RawVec<T, A> {
/// # }
/// ```
pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) {
match self.try_reserve(used_capacity, needed_extra_capacity) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocError { .. }) => unreachable!(),
Err(AllocError { layout, .. }) => handle_alloc_error(layout),
Ok(()) => { /* yay */ }
}
}
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
pub fn try_reserve(
&mut self,
used_capacity: usize,
needed_extra_capacity: usize,
) -> Result<(), TryReserveError> {
if self.needs_to_grow(used_capacity, needed_extra_capacity) {
self.grow(Amortized { used_capacity, needed_extra_capacity }, MayMove, Uninitialized)
} else {
Ok(())
}
}
/// Attempts to ensure that the buffer contains at least enough space to hold
/// `used_capacity + needed_extra_capacity` elements. If it doesn't already have
/// enough capacity, will reallocate in place enough space plus comfortable slack
@ -508,45 +379,54 @@ impl<T, A: AllocRef> RawVec<T, A> {
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
pub fn reserve_in_place(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> bool {
unsafe {
// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
// This is more readable than putting this in one line:
// `!self.needs_to_grow(...) || self.grow(...).is_ok()`
if self.needs_to_grow(used_capacity, needed_extra_capacity) {
self.grow(Amortized { used_capacity, needed_extra_capacity }, InPlace, Uninitialized)
.is_ok()
} else {
true
}
}
// Don't actually need any more capacity. If the current `cap` is 0, we can't
// reallocate in place.
// Wrapping in case they give a bad `used_capacity`
let old_layout = match self.current_layout() {
Some(layout) => layout,
None => return false,
};
if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity {
return false;
}
/// Ensures that the buffer contains at least enough space to hold
/// `used_capacity + needed_extra_capacity` elements. If it doesn't already,
/// will reallocate the minimum possible amount of memory necessary.
/// Generally this will be exactly the amount of memory necessary,
/// but in principle the allocator is free to give back more than
/// we asked for.
///
/// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate
/// the requested space. This is not really unsafe, but the unsafe
/// code *you* write that relies on the behavior of this function may break.
///
/// # Panics
///
/// * Panics if the requested capacity exceeds `usize::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM.
pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) {
match self.try_reserve_exact(used_capacity, needed_extra_capacity) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocError { layout, .. }) => handle_alloc_error(layout),
Ok(()) => { /* yay */ }
}
}
let new_cap = self
.amortized_new_size(used_capacity, needed_extra_capacity)
.unwrap_or_else(|_| capacity_overflow());
// Here, `cap < used_capacity + needed_extra_capacity <= new_cap`
// (regardless of whether `self.cap - used_capacity` wrapped).
// Therefore, we can safely call `grow_in_place`.
let new_layout = Layout::new::<T>().repeat(new_cap).unwrap().0;
// FIXME: may crash and burn on over-reserve
alloc_guard(new_layout.size()).unwrap_or_else(|_| capacity_overflow());
match self.a.grow_in_place(
NonNull::from(self.ptr).cast(),
old_layout,
new_layout.size(),
) {
Ok(_) => {
self.cap = new_cap;
true
}
Err(_) => false,
}
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
pub fn try_reserve_exact(
&mut self,
used_capacity: usize,
needed_extra_capacity: usize,
) -> Result<(), TryReserveError> {
if self.needs_to_grow(used_capacity, needed_extra_capacity) {
self.grow(Exact { used_capacity, needed_extra_capacity }, MayMove, Uninitialized)
} else {
Ok(())
}
}
@ -561,166 +441,157 @@ impl<T, A: AllocRef> RawVec<T, A> {
///
/// Aborts on OOM.
pub fn shrink_to_fit(&mut self, amount: usize) {
let elem_size = mem::size_of::<T>();
// Set the `cap` because they might be about to promote to a `Box<[T]>`
if elem_size == 0 {
self.cap = amount;
return;
}
// This check is my waterloo; it's the only thing `Vec` wouldn't have to do.
assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
if amount == 0 {
// We want to create a new zero-length vector within the
// same allocator. We use `ptr::write` to avoid an
// erroneous attempt to drop the contents, and we use
// `ptr::read` to sidestep condition against destructuring
// types that implement Drop.
unsafe {
let a = ptr::read(&self.a as *const A);
self.dealloc_buffer();
ptr::write(self, RawVec::new_in(a));
}
} else if self.cap != amount {
unsafe {
// We know here that our `amount` is greater than zero. This
// implies, via the assert above, that capacity is also greater
// than zero, which means that we've got a current layout that
// "fits"
//
// We also know that `self.cap` is greater than `amount`, and
// consequently we don't need runtime checks for creating either
// layout.
let old_size = elem_size * self.cap;
let new_size = elem_size * amount;
let align = mem::align_of::<T>();
let old_layout = Layout::from_size_align_unchecked(old_size, align);
match self.a.realloc(NonNull::from(self.ptr).cast(), old_layout, new_size) {
Ok((ptr, _)) => self.ptr = ptr.cast().into(),
Err(_) => {
handle_alloc_error(Layout::from_size_align_unchecked(new_size, align))
}
}
}
self.cap = amount;
match self.shrink(amount, MayMove) {
Err(CapacityOverflow) => capacity_overflow(),
Err(AllocError { layout, .. }) => handle_alloc_error(layout),
Ok(()) => { /* yay */ }
}
}
}
enum Fallibility {
Fallible,
Infallible,
#[derive(Copy, Clone)]
enum Strategy {
Double,
Amortized { used_capacity: usize, needed_extra_capacity: usize },
Exact { used_capacity: usize, needed_extra_capacity: usize },
}
use Fallibility::*;
enum ReserveStrategy {
Exact,
Amortized,
}
use ReserveStrategy::*;
use Strategy::*;
impl<T, A: AllocRef> RawVec<T, A> {
fn reserve_internal(
/// Returns if the buffer needs to grow to fulfill the needed extra capacity.
/// Mainly used to make inlining reserve-calls possible without inlining `grow`.
fn needs_to_grow(&self, used_capacity: usize, needed_extra_capacity: usize) -> bool {
needed_extra_capacity > self.capacity().wrapping_sub(used_capacity)
}
fn capacity_from_bytes(excess: usize) -> usize {
debug_assert_ne!(mem::size_of::<T>(), 0);
excess / mem::size_of::<T>()
}
fn set_memory(&mut self, memory: MemoryBlock) {
self.ptr = memory.ptr.cast().into();
self.cap = Self::capacity_from_bytes(memory.size);
}
/// Single method to handle all possibilities of growing the buffer.
fn grow(
&mut self,
used_capacity: usize,
needed_extra_capacity: usize,
fallibility: Fallibility,
strategy: ReserveStrategy,
strategy: Strategy,
placement: ReallocPlacement,
init: AllocInit,
) -> Result<(), TryReserveError> {
let elem_size = mem::size_of::<T>();
unsafe {
// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
// Don't actually need any more capacity.
// Wrapping in case they gave a bad `used_capacity`.
if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity {
return Ok(());
}
// Nothing we can really do about these checks, sadly.
let new_cap = match strategy {
Exact => {
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?
}
Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?,
};
let new_layout = Layout::array::<T>(new_cap).map_err(|_| CapacityOverflow)?;
alloc_guard(new_layout.size())?;
let res = match self.current_layout() {
Some(layout) => {
debug_assert!(new_layout.align() == layout.align());
self.a.realloc(NonNull::from(self.ptr).cast(), layout, new_layout.size())
}
None => self.a.alloc(new_layout),
};
let (ptr, new_cap) = match (res, fallibility) {
(Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
(Err(AllocErr), Fallible) => {
return Err(TryReserveError::AllocError {
layout: new_layout,
non_exhaustive: (),
});
}
(Ok((ptr, new_size)), _) => (ptr, new_size / elem_size),
};
self.ptr = ptr.cast().into();
self.cap = new_cap;
Ok(())
if elem_size == 0 {
// Since we return a capacity of `usize::MAX` when `elem_size` is
// 0, getting to here necessarily means the `RawVec` is overfull.
return Err(CapacityOverflow);
}
let new_layout = match strategy {
Double => unsafe {
// Since we guarantee that we never allocate more than `isize::MAX` bytes,
// `elem_size * self.cap <= isize::MAX` as a precondition, so this can't overflow.
// Additionally the alignment will never be too large as to "not be satisfiable",
// so `Layout::from_size_align` will always return `Some`.
//
// TL;DR, we bypass runtime checks due to dynamic assertions in this module,
// allowing us to use `from_size_align_unchecked`.
let cap = if self.cap == 0 {
// Skip to 4 because tiny `Vec`'s are dumb; but not if that would cause overflow.
if elem_size > usize::MAX / 8 { 1 } else { 4 }
} else {
self.cap * 2
};
Layout::from_size_align_unchecked(cap * elem_size, mem::align_of::<T>())
},
Amortized { used_capacity, needed_extra_capacity } => {
// Nothing we can really do about these checks, sadly.
let required_cap =
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?;
// Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
let double_cap = self.cap * 2;
// `double_cap` guarantees exponential growth.
let cap = cmp::max(double_cap, required_cap);
Layout::array::<T>(cap).map_err(|_| CapacityOverflow)?
}
Exact { used_capacity, needed_extra_capacity } => {
let cap =
used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?;
Layout::array::<T>(cap).map_err(|_| CapacityOverflow)?
}
};
alloc_guard(new_layout.size())?;
let memory = if let Some((ptr, old_layout)) = self.current_memory() {
debug_assert_eq!(old_layout.align(), new_layout.align());
unsafe {
self.alloc
.grow(ptr, old_layout, new_layout.size(), placement, init)
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
}
} else {
match placement {
MayMove => self.alloc.alloc(new_layout, init),
InPlace => Err(AllocErr),
}
.map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?
};
self.set_memory(memory);
Ok(())
}
fn shrink(
&mut self,
amount: usize,
placement: ReallocPlacement,
) -> Result<(), TryReserveError> {
assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity");
let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) };
let new_size = amount * mem::size_of::<T>();
let memory = unsafe {
self.alloc.shrink(ptr, layout, new_size, placement).map_err(|_| {
TryReserveError::AllocError {
layout: Layout::from_size_align_unchecked(new_size, layout.align()),
non_exhaustive: (),
}
})?
};
self.set_memory(memory);
Ok(())
}
}
impl<T> RawVec<T, Global> {
/// Converts the entire buffer into `Box<[T]>`.
/// Converts the entire buffer into `Box<[MaybeUninit<T>]>` with the specified `len`.
///
/// Note that this will correctly reconstitute any `cap` changes
/// that may have been performed. (See description of type for details.)
///
/// # Undefined Behavior
/// # Safety
///
/// All elements of `RawVec<T, Global>` must be initialized. Notice that
/// the rules around uninitialized boxed values are not finalized yet,
/// but until they are, it is advisable to avoid them.
pub unsafe fn into_box(self) -> Box<[T]> {
/// `shrink_to_fit(len)` must be called immediately prior to calling this function. This
/// implies, that `len` must be smaller than or equal to `self.capacity()`.
pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>]> {
debug_assert!(
len <= self.capacity(),
"`len` must be smaller than or equal to `self.capacity()`"
);
// NOTE: not calling `capacity()` here; actually using the real `cap` field!
let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
let output: Box<[T]> = Box::from_raw(slice);
let slice = slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, len);
let output = Box::from_raw(slice);
mem::forget(self);
output
}
}
impl<T, A: AllocRef> RawVec<T, A> {
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
pub unsafe fn dealloc_buffer(&mut self) {
let elem_size = mem::size_of::<T>();
if elem_size != 0 {
if let Some(layout) = self.current_layout() {
self.a.dealloc(NonNull::from(self.ptr).cast(), layout);
}
}
}
}
unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
fn drop(&mut self) {
unsafe {
self.dealloc_buffer();
if let Some((ptr, layout)) = self.current_memory() {
unsafe { self.alloc.dealloc(ptr, layout) }
}
}
}

View File

@ -12,6 +12,7 @@ fn allocator_param() {
//
// Instead, this just checks that the `RawVec` methods do at
// least go through the Allocator API when it reserves
// storage.
// A dumb allocator that consumes a fixed amount of fuel
@ -20,12 +21,12 @@ fn allocator_param() {
fuel: usize,
}
unsafe impl AllocRef for BoundedAlloc {
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr> {
let size = layout.size();
if size > self.fuel {
return Err(AllocErr);
}
match Global.alloc(layout) {
match Global.alloc(layout, init) {
ok @ Ok(_) => {
self.fuel -= size;
ok
@ -40,9 +41,9 @@ fn allocator_param() {
let a = BoundedAlloc { fuel: 500 };
let mut v: RawVec<u8, _> = RawVec::with_capacity_in(50, a);
assert_eq!(v.a.fuel, 450);
assert_eq!(v.alloc.fuel, 450);
v.reserve(50, 150); // (causes a realloc, thus using 50 + 150 = 200 units of fuel)
assert_eq!(v.a.fuel, 250);
assert_eq!(v.alloc.fuel, 250);
}
#[test]

View File

@ -252,7 +252,7 @@ use core::ptr::{self, NonNull};
use core::slice::{self, from_raw_parts_mut};
use core::usize;
use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocInit, AllocRef, Global, Layout};
use crate::string::String;
use crate::vec::Vec;
@ -936,10 +936,12 @@ impl<T: ?Sized> Rc<T> {
let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align();
// Allocate for the layout.
let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
let mem = Global
.alloc(layout, AllocInit::Uninitialized)
.unwrap_or_else(|_| handle_alloc_error(layout));
// Initialize the RcBox
let inner = mem_to_rcbox(mem.as_ptr());
let inner = mem_to_rcbox(mem.ptr.as_ptr());
debug_assert_eq!(Layout::for_value(&*inner), layout);
ptr::write(&mut (*inner).strong, Cell::new(1));

View File

@ -432,7 +432,7 @@ impl<T> [T] {
///
/// ```should_panic
/// // this will panic at runtime
/// b"0123456789abcdef".repeat(usize::max_value());
/// b"0123456789abcdef".repeat(usize::MAX);
/// ```
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
pub fn repeat(&self, n: usize) -> Vec<T>

View File

@ -499,7 +499,7 @@ impl str {
///
/// ```should_panic
/// // this will panic at runtime
/// "0123456789abcdef".repeat(usize::max_value());
/// "0123456789abcdef".repeat(usize::MAX);
/// ```
#[stable(feature = "repeat_str", since = "1.16.0")]
pub fn repeat(&self, n: usize) -> String {

View File

@ -1849,6 +1849,21 @@ impl<'a, 'b> Pattern<'a> for &'b String {
fn is_prefix_of(self, haystack: &'a str) -> bool {
self[..].is_prefix_of(haystack)
}
#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
self[..].strip_prefix_of(haystack)
}
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool {
self[..].is_suffix_of(haystack)
}
#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
self[..].strip_suffix_of(haystack)
}
}
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -25,7 +25,7 @@ use core::sync::atomic;
use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
use core::{isize, usize};
use crate::alloc::{box_free, handle_alloc_error, AllocRef, Global, Layout};
use crate::alloc::{box_free, handle_alloc_error, AllocInit, AllocRef, Global, Layout};
use crate::boxed::Box;
use crate::rc::is_dangling;
use crate::string::String;
@ -814,10 +814,12 @@ impl<T: ?Sized> Arc<T> {
// reference (see #54908).
let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align();
let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
let mem = Global
.alloc(layout, AllocInit::Uninitialized)
.unwrap_or_else(|_| handle_alloc_error(layout));
// Initialize the ArcInner
let inner = mem_to_arcinner(mem.as_ptr());
let inner = mem_to_arcinner(mem.ptr.as_ptr());
debug_assert_eq!(Layout::for_value(&*inner), layout);
ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));

View File

@ -12,10 +12,12 @@ use crate::sync::Arc;
/// to the tasks that are executed on that executor.
///
/// This trait is a memory-safe and ergonomic alternative to constructing a
/// [`RawWaker`]. It supports the common executor design in which the data
/// used to wake up a task is stored in an [`Arc`]. Some executors (especially
/// [`RawWaker`]. It supports the common executor design in which the data used
/// to wake up a task is stored in an [`Arc`][arc]. Some executors (especially
/// those for embedded systems) cannot use this API, which is why [`RawWaker`]
/// exists as an alternative for those systems.
///
/// [arc]: ../../std/sync/struct.Arc.html
#[unstable(feature = "wake_trait", issue = "69912")]
pub trait Wake {
/// Wake this task.

View File

@ -5,7 +5,7 @@ use std::fmt::Debug;
use std::iter::FromIterator;
use std::ops::Bound::{self, Excluded, Included, Unbounded};
use std::ops::RangeBounds;
use std::panic::catch_unwind;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -528,7 +528,7 @@ fn test_range_1000() {
#[cfg(not(miri))] // Miri is too slow
let size = 1000;
#[cfg(miri)]
let size = MIN_INSERTS_HEIGHT_2;
let size = MIN_INSERTS_HEIGHT_2 as u32;
let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
@ -609,6 +609,263 @@ fn test_range_mut() {
}
}
mod test_drain_filter {
use super::*;
#[test]
fn empty() {
let mut map: BTreeMap<i32, i32> = BTreeMap::new();
map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
assert!(map.is_empty());
}
#[test]
fn consuming_nothing() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
}
#[test]
fn consuming_all() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.clone().collect();
assert!(map.drain_filter(|_, _| true).eq(pairs));
}
#[test]
fn mutating_and_keeping() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
assert!(
map.drain_filter(|_, v| {
*v += 6;
false
})
.eq(std::iter::empty())
);
assert!(map.keys().copied().eq(0..3));
assert!(map.values().copied().eq(6..9));
}
#[test]
fn mutating_and_removing() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
assert!(
map.drain_filter(|_, v| {
*v += 6;
true
})
.eq((0..3).map(|i| (i, i + 6)))
);
assert!(map.is_empty());
}
#[test]
fn underfull_keeping_all() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| false);
assert!(map.keys().copied().eq(0..3));
}
#[test]
fn underfull_removing_one() {
let pairs = (0..3).map(|i| (i, i));
for doomed in 0..3 {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i == doomed);
assert_eq!(map.len(), 2);
}
}
#[test]
fn underfull_keeping_one() {
let pairs = (0..3).map(|i| (i, i));
for sacred in 0..3 {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i != sacred);
assert!(map.keys().copied().eq(sacred..=sacred));
}
}
#[test]
fn underfull_removing_all() {
let pairs = (0..3).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| true);
assert!(map.is_empty());
}
#[test]
fn height_0_keeping_all() {
let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| false);
assert!(map.keys().copied().eq(0..NODE_CAPACITY));
}
#[test]
fn height_0_removing_one() {
let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
for doomed in 0..NODE_CAPACITY {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i == doomed);
assert_eq!(map.len(), NODE_CAPACITY - 1);
}
}
#[test]
fn height_0_keeping_one() {
let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
for sacred in 0..NODE_CAPACITY {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i != sacred);
assert!(map.keys().copied().eq(sacred..=sacred));
}
}
#[test]
fn height_0_removing_all() {
let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| true);
assert!(map.is_empty());
}
#[test]
fn height_0_keeping_half() {
let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect();
assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8);
assert_eq!(map.len(), 8);
}
#[test]
fn height_1_removing_all() {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| true);
assert!(map.is_empty());
}
#[test]
fn height_1_removing_one() {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
for doomed in 0..MIN_INSERTS_HEIGHT_1 {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i == doomed);
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
}
}
#[test]
fn height_1_keeping_one() {
let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
for sacred in 0..MIN_INSERTS_HEIGHT_1 {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i != sacred);
assert!(map.keys().copied().eq(sacred..=sacred));
}
}
#[cfg(not(miri))] // Miri is too slow
#[test]
fn height_2_removing_one() {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i == doomed);
assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
}
}
#[cfg(not(miri))] // Miri is too slow
#[test]
fn height_2_keeping_one() {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
let mut map: BTreeMap<_, _> = pairs.clone().collect();
map.drain_filter(|i, _| *i != sacred);
assert!(map.keys().copied().eq(sacred..=sacred));
}
}
#[test]
fn height_2_removing_all() {
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
let mut map: BTreeMap<_, _> = pairs.collect();
map.drain_filter(|_, _| true);
assert!(map.is_empty());
}
#[test]
fn drop_panic_leak() {
static PREDS: AtomicUsize = AtomicUsize::new(0);
static DROPS: AtomicUsize = AtomicUsize::new(0);
struct D;
impl Drop for D {
fn drop(&mut self) {
if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
panic!("panic in `drop`");
}
}
}
let mut map = BTreeMap::new();
map.insert(0, D);
map.insert(4, D);
map.insert(8, D);
catch_unwind(move || {
drop(map.drain_filter(|i, _| {
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
true
}))
})
.ok();
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
}
#[test]
fn pred_panic_leak() {
static PREDS: AtomicUsize = AtomicUsize::new(0);
static DROPS: AtomicUsize = AtomicUsize::new(0);
struct D;
impl Drop for D {
fn drop(&mut self) {
DROPS.fetch_add(1, Ordering::SeqCst);
}
}
let mut map = BTreeMap::new();
map.insert(0, D);
map.insert(4, D);
map.insert(8, D);
catch_unwind(AssertUnwindSafe(|| {
drop(map.drain_filter(|i, _| {
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
match i {
0 => true,
_ => panic!(),
}
}))
}))
.ok();
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
assert_eq!(map.len(), 2);
assert_eq!(map.first_entry().unwrap().key(), &4);
assert_eq!(map.last_entry().unwrap().key(), &8);
}
}
#[test]
fn test_borrow() {
// make sure these compile -- using the Borrow trait

View File

@ -1,5 +1,7 @@
use std::collections::BTreeSet;
use std::iter::FromIterator;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::atomic::{AtomicU32, Ordering};
use super::DeterministicRng;
@ -302,6 +304,85 @@ fn test_is_subset() {
assert_eq!(is_subset(&[99, 100], &large), false);
}
#[test]
fn test_drain_filter() {
let mut x: BTreeSet<_> = [1].iter().copied().collect();
let mut y: BTreeSet<_> = [1].iter().copied().collect();
x.drain_filter(|_| true);
y.drain_filter(|_| false);
assert_eq!(x.len(), 0);
assert_eq!(y.len(), 1);
}
#[test]
fn test_drain_filter_drop_panic_leak() {
static PREDS: AtomicU32 = AtomicU32::new(0);
static DROPS: AtomicU32 = AtomicU32::new(0);
#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct D(i32);
impl Drop for D {
fn drop(&mut self) {
if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
panic!("panic in `drop`");
}
}
}
let mut set = BTreeSet::new();
set.insert(D(0));
set.insert(D(4));
set.insert(D(8));
catch_unwind(move || {
drop(set.drain_filter(|d| {
PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
true
}))
})
.ok();
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
}
#[test]
fn test_drain_filter_pred_panic_leak() {
static PREDS: AtomicU32 = AtomicU32::new(0);
static DROPS: AtomicU32 = AtomicU32::new(0);
#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct D(i32);
impl Drop for D {
fn drop(&mut self) {
DROPS.fetch_add(1, Ordering::SeqCst);
}
}
let mut set = BTreeSet::new();
set.insert(D(0));
set.insert(D(4));
set.insert(D(8));
catch_unwind(AssertUnwindSafe(|| {
drop(set.drain_filter(|d| {
PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
match d.0 {
0 => true,
_ => panic!(),
}
}))
}))
.ok();
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
assert_eq!(set.len(), 2);
assert_eq!(set.first().unwrap().0, 4);
assert_eq!(set.last().unwrap().0, 8);
}
#[test]
fn test_clear() {
let mut x = BTreeSet::new();

View File

@ -1,4 +1,4 @@
use std::alloc::{AllocRef, Global, Layout, System};
use std::alloc::{AllocInit, AllocRef, Global, Layout, System};
/// Issue #45955 and #62251.
#[test]
@ -20,7 +20,13 @@ fn check_overalign_requests<T: AllocRef>(mut allocator: T) {
unsafe {
let pointers: Vec<_> = (0..iterations)
.map(|_| {
allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap().0
allocator
.alloc(
Layout::from_size_align(size, align).unwrap(),
AllocInit::Uninitialized,
)
.unwrap()
.ptr
})
.collect();
for &ptr in &pointers {

View File

@ -1,5 +1,6 @@
#![feature(allocator_api)]
#![feature(box_syntax)]
#![feature(btree_drain_filter)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(map_first_last)]

View File

@ -679,8 +679,9 @@ impl<T> Vec<T> {
unsafe {
self.shrink_to_fit();
let buf = ptr::read(&self.buf);
let len = self.len();
mem::forget(self);
buf.into_box()
buf.into_box(len).assume_init()
}
}

File diff suppressed because it is too large Load Diff

198
src/libcore/alloc/global.rs Normal file
View File

@ -0,0 +1,198 @@
use crate::alloc::Layout;
use crate::cmp;
use crate::ptr;
/// A memory allocator that can be registered as the standard librarys default
/// through the `#[global_allocator]` attribute.
///
/// Some of the methods require that a memory block be *currently
/// allocated* via an allocator. This means that:
///
/// * the starting address for that memory block was previously
/// returned by a previous call to an allocation method
/// such as `alloc`, and
///
/// * the memory block has not been subsequently deallocated, where
/// blocks are deallocated either by being passed to a deallocation
/// method such as `dealloc` or by being
/// passed to a reallocation method that returns a non-null pointer.
///
///
/// # Example
///
/// ```no_run
/// use std::alloc::{GlobalAlloc, Layout, alloc};
/// use std::ptr::null_mut;
///
/// struct MyAllocator;
///
/// unsafe impl GlobalAlloc for MyAllocator {
/// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
/// }
///
/// #[global_allocator]
/// static A: MyAllocator = MyAllocator;
///
/// fn main() {
/// unsafe {
/// assert!(alloc(Layout::new::<u32>()).is_null())
/// }
/// }
/// ```
///
/// # Safety
///
/// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
/// implementors must ensure that they adhere to these contracts:
///
/// * It's undefined behavior if global allocators unwind. This restriction may
/// be lifted in the future, but currently a panic from any of these
/// functions may lead to memory unsafety.
///
/// * `Layout` queries and calculations in general must be correct. Callers of
/// this trait are allowed to rely on the contracts defined on each method,
/// and implementors must ensure such contracts remain true.
#[stable(feature = "global_alloc", since = "1.28.0")]
pub unsafe trait GlobalAlloc {
/// Allocate memory as described by the given `layout`.
///
/// Returns a pointer to newly-allocated memory,
/// or null to indicate allocation failure.
///
/// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure that `layout` has non-zero size.
///
/// (Extension subtraits might provide more specific bounds on
/// behavior, e.g., guarantee a sentinel address or a null pointer
/// in response to a zero-size allocation request.)
///
/// The allocated block of memory may or may not be initialized.
///
/// # Errors
///
/// Returning a null pointer indicates that either memory is exhausted
/// or `layout` does not meet this allocator's size or alignment constraints.
///
/// Implementations are encouraged to return null on memory
/// exhaustion rather than aborting, but this is not
/// a strict requirement. (Specifically: it is *legal* to
/// implement this trait atop an underlying native allocation
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an
/// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn alloc(&self, layout: Layout) -> *mut u8;
/// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
///
/// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
///
/// * `ptr` must denote a block of memory currently allocated via
/// this allocator,
///
/// * `layout` must be the same layout that was used
/// to allocate that block of memory,
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
/// Behaves like `alloc`, but also ensures that the contents
/// are set to zero before being returned.
///
/// # Safety
///
/// This function is unsafe for the same reasons that `alloc` is.
/// However the allocated block of memory is guaranteed to be initialized.
///
/// # Errors
///
/// Returning a null pointer indicates that either memory is exhausted
/// or `layout` does not meet allocator's size or alignment constraints,
/// just as in `alloc`.
///
/// Clients wishing to abort computation in response to an
/// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let size = layout.size();
let ptr = self.alloc(layout);
if !ptr.is_null() {
ptr::write_bytes(ptr, 0, size);
}
ptr
}
/// Shrink or grow a block of memory to the given `new_size`.
/// The block is described by the given `ptr` pointer and `layout`.
///
/// If this returns a non-null pointer, then ownership of the memory block
/// referenced by `ptr` has been transferred to this allocator.
/// The memory may or may not have been deallocated,
/// and should be considered unusable (unless of course it was
/// transferred back to the caller again via the return value of
/// this method). The new memory block is allocated with `layout`, but
/// with the `size` updated to `new_size`.
///
/// If this method returns null, then ownership of the memory
/// block has not been transferred to this allocator, and the
/// contents of the memory block are unaltered.
///
/// # Safety
///
/// This function is unsafe because undefined behavior can result
/// if the caller does not ensure all of the following:
///
/// * `ptr` must be currently allocated via this allocator,
///
/// * `layout` must be the same layout that was used
/// to allocate that block of memory,
///
/// * `new_size` must be greater than zero.
///
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
/// must not overflow (i.e., the rounded value must be less than `usize::MAX`).
///
/// (Extension subtraits might provide more specific bounds on
/// behavior, e.g., guarantee a sentinel address or a null pointer
/// in response to a zero-size allocation request.)
///
/// # Errors
///
/// Returns null if the new layout does not meet the size
/// and alignment constraints of the allocator, or if reallocation
/// otherwise fails.
///
/// Implementations are encouraged to return null on memory
/// exhaustion rather than panicking or aborting, but this is not
/// a strict requirement. (Specifically: it is *legal* to
/// implement this trait atop an underlying native allocation
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to a
/// reallocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
let new_ptr = self.alloc(new_layout);
if !new_ptr.is_null() {
ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
self.dealloc(ptr, layout);
}
new_ptr
}
}

346
src/libcore/alloc/layout.rs Normal file
View File

@ -0,0 +1,346 @@
// ignore-tidy-undocumented-unsafe
use crate::cmp;
use crate::fmt;
use crate::mem;
use crate::num::NonZeroUsize;
use crate::ptr::NonNull;
const fn size_align<T>() -> (usize, usize) {
(mem::size_of::<T>(), mem::align_of::<T>())
}
/// Layout of a block of memory.
///
/// An instance of `Layout` describes a particular layout of memory.
/// You build a `Layout` up as an input to give to an allocator.
///
/// All layouts have an associated size and a power-of-two alignment.
///
/// (Note that layouts are *not* required to have non-zero size,
/// even though `GlobalAlloc` requires that all memory requests
/// be non-zero in size. A caller must either ensure that conditions
/// like this are met, use specific allocators with looser
/// requirements, or use the more lenient `AllocRef` interface.)
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[lang = "alloc_layout"]
pub struct Layout {
// size of the requested block of memory, measured in bytes.
size_: usize,
// alignment of the requested block of memory, measured in bytes.
// we ensure that this is always a power-of-two, because API's
// like `posix_memalign` require it and it is a reasonable
// constraint to impose on Layout constructors.
//
// (However, we do not analogously require `align >= sizeof(void*)`,
// even though that is *also* a requirement of `posix_memalign`.)
align_: NonZeroUsize,
}
impl Layout {
/// Constructs a `Layout` from a given `size` and `align`,
/// or returns `LayoutErr` if any of the following conditions
/// are not met:
///
/// * `align` must not be zero,
///
/// * `align` must be a power of two,
///
/// * `size`, when rounded up to the nearest multiple of `align`,
/// must not overflow (i.e., the rounded value must be less than
/// or equal to `usize::MAX`).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
if !align.is_power_of_two() {
return Err(LayoutErr { private: () });
}
// (power-of-two implies align != 0.)
// Rounded up size is:
// size_rounded_up = (size + align - 1) & !(align - 1);
//
// We know from above that align != 0. If adding (align - 1)
// does not overflow, then rounding up will be fine.
//
// Conversely, &-masking with !(align - 1) will subtract off
// only low-order-bits. Thus if overflow occurs with the sum,
// the &-mask cannot subtract enough to undo that overflow.
//
// Above implies that checking for summation overflow is both
// necessary and sufficient.
if size > usize::MAX - (align - 1) {
return Err(LayoutErr { private: () });
}
unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
}
/// Creates a layout, bypassing all checks.
///
/// # Safety
///
/// This function is unsafe as it does not verify the preconditions from
/// [`Layout::from_size_align`](#method.from_size_align).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
#[inline]
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
}
/// The minimum size in bytes for a memory block of this layout.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub const fn size(&self) -> usize {
self.size_
}
/// The minimum byte alignment for a memory block of this layout.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub const fn align(&self) -> usize {
self.align_.get()
}
/// Constructs a `Layout` suitable for holding a value of type `T`.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
#[inline]
pub const fn new<T>() -> Self {
let (size, align) = size_align::<T>();
// Note that the align is guaranteed by rustc to be a power of two and
// the size+align combo is guaranteed to fit in our address space. As a
// result use the unchecked constructor here to avoid inserting code
// that panics if it isn't optimized well enough.
unsafe { Layout::from_size_align_unchecked(size, align) }
}
/// Produces layout describing a record that could be used to
/// allocate backing structure for `T` (which could be a trait
/// or other unsized type like a slice).
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[inline]
pub fn for_value<T: ?Sized>(t: &T) -> Self {
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
// See rationale in `new` for why this is using an unsafe variant below
debug_assert!(Layout::from_size_align(size, align).is_ok());
unsafe { Layout::from_size_align_unchecked(size, align) }
}
/// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
///
/// Note that the pointer value may potentially represent a valid pointer,
/// which means this must not be used as a "not yet initialized"
/// sentinel value. Types that lazily allocate must track initialization by
/// some other means.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub const fn dangling(&self) -> NonNull<u8> {
// align is non-zero and a power of two
unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
}
/// Creates a layout describing the record that can hold a value
/// of the same layout as `self`, but that also is aligned to
/// alignment `align` (measured in bytes).
///
/// If `self` already meets the prescribed alignment, then returns
/// `self`.
///
/// Note that this method does not add any padding to the overall
/// size, regardless of whether the returned layout has a different
/// alignment. In other words, if `K` has size 16, `K.align_to(32)`
/// will *still* have size 16.
///
/// Returns an error if the combination of `self.size()` and the given
/// `align` violates the conditions listed in
/// [`Layout::from_size_align`](#method.from_size_align).
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
Layout::from_size_align(self.size(), cmp::max(self.align(), align))
}
/// Returns the amount of padding we must insert after `self`
/// to ensure that the following address will satisfy `align`
/// (measured in bytes).
///
/// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
/// returns 3, because that is the minimum number of bytes of
/// padding required to get a 4-aligned address (assuming that the
/// corresponding memory block starts at a 4-aligned address).
///
/// The return value of this function has no meaning if `align` is
/// not a power-of-two.
///
/// Note that the utility of the returned value requires `align`
/// to be less than or equal to the alignment of the starting
/// address for the whole allocated block of memory. One way to
/// satisfy this constraint is to ensure `align <= self.align()`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
#[inline]
pub const fn padding_needed_for(&self, align: usize) -> usize {
let len = self.size();
// Rounded up value is:
// len_rounded_up = (len + align - 1) & !(align - 1);
// and then we return the padding difference: `len_rounded_up - len`.
//
// We use modular arithmetic throughout:
//
// 1. align is guaranteed to be > 0, so align - 1 is always
// valid.
//
// 2. `len + align - 1` can overflow by at most `align - 1`,
// so the &-mask with `!(align - 1)` will ensure that in the
// case of overflow, `len_rounded_up` will itself be 0.
// Thus the returned padding, when added to `len`, yields 0,
// which trivially satisfies the alignment `align`.
//
// (Of course, attempts to allocate blocks of memory whose
// size and padding overflow in the above manner should cause
// the allocator to yield an error anyway.)
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
len_rounded_up.wrapping_sub(len)
}
/// Creates a layout by rounding the size of this layout up to a multiple
/// of the layout's alignment.
///
/// This is equivalent to adding the result of `padding_needed_for`
/// to the layout's current size.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn pad_to_align(&self) -> Layout {
let pad = self.padding_needed_for(self.align());
// This cannot overflow. Quoting from the invariant of Layout:
// > `size`, when rounded up to the nearest multiple of `align`,
// > must not overflow (i.e., the rounded value must be less than
// > `usize::MAX`)
let new_size = self.size() + pad;
Layout::from_size_align(new_size, self.align()).unwrap()
}
/// Creates a layout describing the record for `n` instances of
/// `self`, with a suitable amount of padding between each to
/// ensure that each instance is given its requested size and
/// alignment. On success, returns `(k, offs)` where `k` is the
/// layout of the array and `offs` is the distance between the start
/// of each element in the array.
///
/// On arithmetic overflow, returns `LayoutErr`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
// This cannot overflow. Quoting from the invariant of Layout:
// > `size`, when rounded up to the nearest multiple of `align`,
// > must not overflow (i.e., the rounded value must be less than
// > `usize::MAX`)
let padded_size = self.size() + self.padding_needed_for(self.align());
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
unsafe {
// self.align is already known to be valid and alloc_size has been
// padded already.
Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size))
}
}
/// Creates a layout describing the record for `self` followed by
/// `next`, including any necessary padding to ensure that `next`
/// will be properly aligned. Note that the resulting layout will
/// satisfy the alignment properties of both `self` and `next`.
///
/// The resulting layout will be the same as that of a C struct containing
/// two fields with the layouts of `self` and `next`, in that order.
///
/// Returns `Some((k, offset))`, where `k` is layout of the concatenated
/// record and `offset` is the relative location, in bytes, of the
/// start of the `next` embedded within the concatenated record
/// (assuming that the record itself starts at offset 0).
///
/// On arithmetic overflow, returns `LayoutErr`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
let new_align = cmp::max(self.align(), next.align());
let pad = self.padding_needed_for(next.align());
let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
let layout = Layout::from_size_align(new_size, new_align)?;
Ok((layout, offset))
}
/// Creates a layout describing the record for `n` instances of
/// `self`, with no padding between each instance.
///
/// Note that, unlike `repeat`, `repeat_packed` does not guarantee
/// that the repeated instances of `self` will be properly
/// aligned, even if a given instance of `self` is properly
/// aligned. In other words, if the layout returned by
/// `repeat_packed` is used to allocate an array, it is not
/// guaranteed that all elements in the array will be properly
/// aligned.
///
/// On arithmetic overflow, returns `LayoutErr`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
Layout::from_size_align(size, self.align())
}
/// Creates a layout describing the record for `self` followed by
/// `next` with no additional padding between the two. Since no
/// padding is inserted, the alignment of `next` is irrelevant,
/// and is not incorporated *at all* into the resulting layout.
///
/// On arithmetic overflow, returns `LayoutErr`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
Layout::from_size_align(new_size, self.align())
}
/// Creates a layout describing the record for a `[T; n]`.
///
/// On arithmetic overflow, returns `LayoutErr`.
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
#[inline]
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
Layout::new::<T>().repeat(n).map(|(k, offs)| {
debug_assert!(offs == mem::size_of::<T>());
k
})
}
}
/// The parameters given to `Layout::from_size_align`
/// or some other `Layout` constructor
/// do not satisfy its documented constraints.
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LayoutErr {
private: (),
}
// (we need this for downstream impl of trait Error)
#[stable(feature = "alloc_layout", since = "1.28.0")]
impl fmt::Display for LayoutErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("invalid parameters to Layout::from_size_align")
}
}

367
src/libcore/alloc/mod.rs Normal file
View File

@ -0,0 +1,367 @@
//! Memory allocation APIs
#![stable(feature = "alloc_module", since = "1.28.0")]
mod global;
mod layout;
#[stable(feature = "global_alloc", since = "1.28.0")]
pub use self::global::GlobalAlloc;
#[stable(feature = "alloc_layout", since = "1.28.0")]
pub use self::layout::{Layout, LayoutErr};
use crate::fmt;
use crate::ptr::{self, NonNull};
/// The `AllocErr` error indicates an allocation failure
/// that may be due to resource exhaustion or to
/// something wrong when combining the given input arguments with this
/// allocator.
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AllocErr;
// (we need this for downstream impl of trait Error)
#[unstable(feature = "allocator_api", issue = "32838")]
impl fmt::Display for AllocErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("memory allocation failed")
}
}
/// A desired initial state for allocated memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum AllocInit {
/// The contents of the new memory are uninitialized.
Uninitialized,
/// The new memory is guaranteed to be zeroed.
Zeroed,
}
impl AllocInit {
/// Initialize the specified memory block.
///
/// This behaves like calling [`AllocInit::init_offset(memory, 0)`][off].
///
/// [off]: AllocInit::init_offset
///
/// # Safety
///
/// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
///
/// [valid]: ../../core/ptr/index.html#safety
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe fn init(self, memory: MemoryBlock) {
self.init_offset(memory, 0)
}
/// Initialize the memory block like specified by `init` at the specified `offset`.
///
/// This is a no-op for [`AllocInit::Uninitialized`][] and writes zeroes for
/// [`AllocInit::Zeroed`][] at `ptr + offset` until `ptr + layout.size()`.
///
/// # Safety
///
/// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
/// * `offset` must be smaller than or equal to `memory.size`
///
/// [valid]: ../../core/ptr/index.html#safety
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe fn init_offset(self, memory: MemoryBlock, offset: usize) {
debug_assert!(
offset <= memory.size,
"`offset` must be smaller than or equal to `memory.size`"
);
match self {
AllocInit::Uninitialized => (),
AllocInit::Zeroed => {
memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset)
}
}
}
}
/// Represents a block of allocated memory returned by an allocator.
#[derive(Debug, Copy, Clone)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub struct MemoryBlock {
pub ptr: NonNull<u8>,
pub size: usize,
}
/// A placement constraint when growing or shrinking an existing allocation.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum ReallocPlacement {
/// The allocator is allowed to move the allocation to a different memory address.
// FIXME(wg-allocators#46): Add a section to the module documentation "What is a legal
// allocator" and link it at "valid location".
///
/// If the allocation _does_ move, it's the responsibility of the allocator
/// to also move the data from the previous location to the new location.
MayMove,
/// The address of the new memory must not change.
///
/// If the allocation would have to be moved to a new location to fit, the
/// reallocation request will fail.
InPlace,
}
/// An implementation of `AllocRef` can allocate, grow, shrink, and deallocate arbitrary blocks of
/// data described via [`Layout`][].
///
/// `AllocRef` is designed to be implemented on ZSTs, references, or smart pointers because having
/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
/// allocated memory.
///
/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `AllocRef`. If an underlying
/// allocator does not support this (like jemalloc) or return a null pointer (such as
/// `libc::malloc`), this must be caught by the implementation.
///
/// ### Currently allocated memory
///
/// Some of the methods require that a memory block be *currently allocated* via an allocator. This
/// means that:
///
/// * the starting address for that memory block was previously returned by [`alloc`], [`grow`], or
/// [`shrink`], and
///
/// * the memory block has not been subsequently deallocated, where blocks are either deallocated
/// directly by being passed to [`dealloc`] or were changed by being passed to [`grow`] or
/// [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer
/// remains valid.
///
/// [`alloc`]: AllocRef::alloc
/// [`grow`]: AllocRef::grow
/// [`shrink`]: AllocRef::shrink
/// [`dealloc`]: AllocRef::dealloc
///
/// ### Memory fitting
///
/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to
/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the
/// following conditions must hold:
///
/// * The block must be allocated with the same alignment as [`layout.align()`], and
///
/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where:
/// - `min` is the size of the layout most recently used to allocate the block, and
/// - `max` is the latest actual size returned from [`alloc`], [`grow`], or [`shrink`].
///
/// [`layout.align()`]: Layout::align
/// [`layout.size()`]: Layout::size
///
/// # Safety
///
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
/// until the instance and all of its clones are dropped,
///
/// * cloning or moving the allocator must not invalidate memory blocks returned from this
/// allocator. A cloned allocator must behave like the same allocator, and
///
/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other
/// method of the allocator.
///
/// [*currently allocated*]: #currently-allocated-memory
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe trait AllocRef {
/// Attempts to allocate a block of memory.
///
/// On success, returns a [`MemoryBlock`][] meeting the size and alignment guarantees of `layout`.
///
/// The returned block may have a larger size than specified by `layout.size()` and is
/// initialized as specified by [`init`], all the way up to the returned size of the block.
///
/// [`init`]: AllocInit
///
/// # Errors
///
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
/// allocator's size or alignment constraints.
///
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an allocation error are encouraged to
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr>;
/// Deallocates the memory referenced by `ptr`.
///
/// # Safety
///
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and
/// * `layout` must [*fit*] that block of memory.
///
/// [*currently allocated*]: #currently-allocated-memory
/// [*fit*]: #memory-fitting
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
/// Attempts to extend the memory block.
///
/// Returns a new [`MemoryBlock`][] containing a pointer and the actual size of the allocated
/// memory. The pointer is suitable for holding data described by a new layout with `layout`s
/// alignment and a size given by `new_size`. To accomplish this, the allocator may extend the
/// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
/// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
///
/// If [`MayMove`] is used then ownership of the memory block referenced by `ptr`
/// is transferred to this allocator. The memory may or may not be freed, and should be
/// considered unusable (unless of course it is transferred back to the caller again via the
/// return value of this method).
///
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
/// this allocator, and the contents of the memory block are unaltered.
///
/// The memory block will contain the following contents after a successful call to `grow`:
/// * Bytes `0..layout.size()` are preserved from the original allocation.
/// * Bytes `layout.size()..old_size` will either be preserved or initialized according to
/// [`init`], depending on the allocator implementation. `old_size` refers to the size of
/// the `MemoryBlock` prior to the `grow` call, which may be larger than the size
/// that was originally requested when it was allocated.
/// * Bytes `old_size..new_size` are initialized according to [`init`]. `new_size` refers to
/// the size of the `MemoryBlock` returned by the `grow` call.
///
/// [`InPlace`]: ReallocPlacement::InPlace
/// [`MayMove`]: ReallocPlacement::MayMove
/// [`placement`]: ReallocPlacement
/// [`init`]: AllocInit
///
/// # Safety
///
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
/// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.),
// We can't require that `new_size` is strictly greater than `memory.size` because of ZSTs.
// An alternative would be
// * `new_size must be strictly greater than `memory.size` or both are zero
/// * `new_size` must be greater than or equal to `layout.size()`, and
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
/// (i.e., the rounded value must be less than or equal to `usize::MAX`).
///
/// [*currently allocated*]: #currently-allocated-memory
/// [*fit*]: #memory-fitting
///
/// # Errors
///
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
/// constraints of the allocator, or if growing otherwise fails.
///
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an allocation error are encouraged to
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn grow(
&mut self,
ptr: NonNull<u8>,
layout: Layout,
new_size: usize,
placement: ReallocPlacement,
init: AllocInit,
) -> Result<MemoryBlock, AllocErr> {
match placement {
ReallocPlacement::InPlace => Err(AllocErr),
ReallocPlacement::MayMove => {
let size = layout.size();
debug_assert!(
new_size >= size,
"`new_size` must be greater than or equal to `layout.size()`"
);
if new_size == size {
return Ok(MemoryBlock { ptr, size });
}
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
let new_memory = self.alloc(new_layout, init)?;
ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size);
self.dealloc(ptr, layout);
Ok(new_memory)
}
}
}
/// Attempts to shrink the memory block.
///
/// Returns a new [`MemoryBlock`][] containing a pointer and the actual size of the allocated
/// memory. The pointer is suitable for holding data described by a new layout with `layout`s
/// alignment and a size given by `new_size`. To accomplish this, the allocator may shrink the
/// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
/// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
///
/// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
/// transferred to this allocator. The memory may or may not have been freed, and should be
/// considered unusable unless it was transferred back to the caller again via the
/// return value of this method.
///
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
/// this allocator, and the contents of the memory block are unaltered.
///
/// The behavior of how the allocator tries to shrink the memory is specified by [`placement`].
///
/// [`InPlace`]: ReallocPlacement::InPlace
/// [`placement`]: ReallocPlacement
///
/// # Safety
///
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator,
/// * `layout` must [*fit*] that block of memory (The `new_size` argument need not fit it.), and
// We can't require that `new_size` is strictly smaller than `memory.size` because of ZSTs.
// An alternative would be
// * `new_size must be strictly smaller than `memory.size` or both are zero
/// * `new_size` must be smaller than or equal to `layout.size()`.
///
/// [*currently allocated*]: #currently-allocated-memory
/// [*fit*]: #memory-fitting
///
/// # Errors
///
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
/// constraints of the allocator, or if shrinking otherwise fails.
///
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an allocation error are encouraged to
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
///
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn shrink(
&mut self,
ptr: NonNull<u8>,
layout: Layout,
new_size: usize,
placement: ReallocPlacement,
) -> Result<MemoryBlock, AllocErr> {
match placement {
ReallocPlacement::InPlace => Err(AllocErr),
ReallocPlacement::MayMove => {
let size = layout.size();
debug_assert!(
new_size <= size,
"`new_size` must be smaller than or equal to `layout.size()`"
);
if new_size == size {
return Ok(MemoryBlock { ptr, size });
}
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?;
ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size);
self.dealloc(ptr, layout);
Ok(new_memory)
}
}
}
}

View File

@ -39,7 +39,7 @@ where
alive: Range<usize>,
}
impl<T, const N: usize> IntoIter<T, { N }>
impl<T, const N: usize> IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -99,7 +99,7 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, { N }>
impl<T, const N: usize> Iterator for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -146,7 +146,7 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, { N }>
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -182,7 +182,7 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, { N }>
impl<T, const N: usize> Drop for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -195,7 +195,7 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, { N }>
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -210,17 +210,17 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
impl<T, const N: usize> FusedIterator for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, { N }> where [T; N]: LengthAtMost32 {}
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> where [T; N]: LengthAtMost32 {}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, { N }>
impl<T: Clone, const N: usize> Clone for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{
@ -249,7 +249,7 @@ where
}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, { N }>
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N>
where
[T; N]: LengthAtMost32,
{

View File

@ -169,7 +169,8 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
/// Implementations of `Clone` for primitive types.
///
/// Implementations that cannot be described in Rust
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
/// in `rustc_trait_selection`.
mod impls {
use super::Clone;

View File

@ -817,7 +817,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// When comparison is impossible:
///
/// ```
/// let result = std::f64::NAN.partial_cmp(&1.0);
/// let result = f64::NAN.partial_cmp(&1.0);
/// assert_eq!(result, None);
/// ```
#[must_use]

View File

@ -41,6 +41,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::fmt;
use crate::hash::{Hash, Hasher};
mod num;
@ -746,3 +747,10 @@ impl From<!> for Infallible {
x
}
}
#[stable(feature = "convert_infallible_hash", since = "1.44.0")]
impl Hash for Infallible {
fn hash<H: Hasher>(&self, _: &mut H) {
match *self {}
}
}

View File

@ -13,9 +13,9 @@ mod private {
/// Typically doesnt need to be used directly.
#[unstable(feature = "convert_float_to_int", issue = "67057")]
pub trait FloatToInt<Int>: private::Sealed + Sized {
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
#[unstable(feature = "convert_float_to_int", issue = "67057")]
#[doc(hidden)]
unsafe fn approx_unchecked(self) -> Int;
unsafe fn to_int_unchecked(self) -> Int;
}
macro_rules! impl_float_to_int {
@ -27,8 +27,15 @@ macro_rules! impl_float_to_int {
impl FloatToInt<$Int> for $Float {
#[doc(hidden)]
#[inline]
unsafe fn approx_unchecked(self) -> $Int {
crate::intrinsics::float_to_int_approx_unchecked(self)
unsafe fn to_int_unchecked(self) -> $Int {
#[cfg(bootstrap)]
{
crate::intrinsics::float_to_int_approx_unchecked(self)
}
#[cfg(not(bootstrap))]
{
crate::intrinsics::float_to_int_unchecked(self)
}
}
}
)+

View File

@ -852,7 +852,7 @@ pub trait LowerHex {
/// }
/// }
///
/// let l = Length(i32::max_value());
/// let l = Length(i32::MAX);
///
/// assert_eq!(format!("l as hex is: {:X}", l), "l as hex is: 7FFFFFFF");
///

View File

@ -43,7 +43,7 @@ use crate::intrinsics;
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
/// assert_eq!(div_1(11, std::u32::MAX), 0);
/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]

View File

@ -1582,8 +1582,16 @@ extern "rust-intrinsic" {
/// Convert with LLVMs fptoui/fptosi, which may return undef for values out of range
/// (<https://github.com/rust-lang/rust/issues/10184>)
/// This is under stabilization at <https://github.com/rust-lang/rust/issues/67058>
#[cfg(bootstrap)]
pub fn float_to_int_approx_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
/// Convert with LLVMs fptoui/fptosi, which may return undef for values out of range
/// (<https://github.com/rust-lang/rust/issues/10184>)
///
/// Stabilized as `f32::to_int_unchecked` and `f64::to_int_unchecked`.
#[cfg(not(bootstrap))]
pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
/// Returns the number of bits set in an integer type `T`
///
/// The stabilized versions of this intrinsic are available on the integer
@ -1731,11 +1739,11 @@ extern "rust-intrinsic" {
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
/// Performs an exact division, resulting in undefined behavior where
/// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
/// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
pub fn exact_div<T: Copy>(x: T, y: T) -> T;
/// Performs an unchecked division, resulting in undefined behavior
/// where y = 0 or x = `T::min_value()` and y = -1
/// where y = 0 or x = `T::MIN` and y = -1
///
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `checked_div` method. For example,
@ -1743,7 +1751,7 @@ extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked division, resulting in
/// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
/// undefined behavior where y = 0 or x = `T::MIN` and y = -1
///
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `checked_rem` method. For example,
@ -1769,17 +1777,17 @@ extern "rust-intrinsic" {
pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked addition, resulting in
/// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked subtraction, resulting in
/// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked multiplication, resulting in
/// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;

View File

@ -198,7 +198,7 @@ pub trait Iterator {
/// // and the maximum possible lower bound
/// let iter = 0..;
///
/// assert_eq!((usize::max_value(), None), iter.size_hint());
/// assert_eq!((usize::MAX, None), iter.size_hint());
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -2920,7 +2920,7 @@ pub trait Iterator {
/// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
/// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
///
/// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None);
/// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
@ -3170,7 +3170,7 @@ pub trait Iterator {
/// assert!(![1, 3, 2, 4].iter().is_sorted());
/// assert!([0].iter().is_sorted());
/// assert!(std::iter::empty::<i32>().is_sorted());
/// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
@ -3197,7 +3197,7 @@ pub trait Iterator {
/// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// ```
///
/// [`is_sorted`]: trait.Iterator.html#method.is_sorted

View File

@ -1070,8 +1070,10 @@ pub(crate) mod builtin {
/// Includes a utf8-encoded file as a string.
///
/// The file is located relative to the current file. (similarly to how
/// modules are found)
/// The file is located relative to the current file (similarly to how
/// modules are found). The provided path is interpreted in a platform-specific
/// way at compile time. So, for instance, an invocation with a Windows path
/// containing backslashes `\` would not compile correctly on Unix.
///
/// This macro will yield an expression of type `&'static str` which is the
/// contents of the file.
@ -1108,8 +1110,10 @@ pub(crate) mod builtin {
/// Includes a file as a reference to a byte array.
///
/// The file is located relative to the current file. (similarly to how
/// modules are found)
/// The file is located relative to the current file (similarly to how
/// modules are found). The provided path is interpreted in a platform-specific
/// way at compile time. So, for instance, an invocation with a Windows path
/// containing backslashes `\` would not compile correctly on Unix.
///
/// This macro will yield an expression of type `&'static [u8; N]` which is
/// the contents of the file.
@ -1202,7 +1206,9 @@ pub(crate) mod builtin {
/// Parses a file as an expression or an item according to the context.
///
/// The file is located relative to the current file (similarly to how
/// modules are found).
/// modules are found). The provided path is interpreted in a platform-specific
/// way at compile time. So, for instance, an invocation with a Windows path
/// containing backslashes `\` would not compile correctly on Unix.
///
/// Using this macro is often a bad idea, because if the file is
/// parsed as an expression, it is going to be placed in the

View File

@ -759,7 +759,8 @@ impl<T: ?Sized> Unpin for *mut T {}
/// Implementations of `Copy` for primitive types.
///
/// Implementations that cannot be described in Rust
/// are implemented in `SelectionContext::copy_clone_conditions()` in librustc.
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
/// in `rustc_trait_selection`.
mod copy_impls {
use super::Copy;

View File

@ -464,15 +464,13 @@ impl f32 {
/// assuming that the value is finite and fits in that type.
///
/// ```
/// #![feature(float_approx_unchecked_to)]
///
/// let value = 4.6_f32;
/// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
/// assert_eq!(rounded, 4);
///
/// let value = -128.9_f32;
/// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
/// assert_eq!(rounded, std::i8::MIN);
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
/// assert_eq!(rounded, i8::MIN);
/// ```
///
/// # Safety
@ -482,13 +480,13 @@ impl f32 {
/// * Not be `NaN`
/// * Not be infinite
/// * Be representable in the return type `Int`, after truncating off its fractional part
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
#[inline]
pub unsafe fn approx_unchecked_to<Int>(self) -> Int
pub unsafe fn to_int_unchecked<Int>(self) -> Int
where
Self: FloatToInt<Int>,
{
FloatToInt::<Int>::approx_unchecked(self)
FloatToInt::<Int>::to_int_unchecked(self)
}
/// Raw transmutation to `u32`.

View File

@ -478,15 +478,13 @@ impl f64 {
/// assuming that the value is finite and fits in that type.
///
/// ```
/// #![feature(float_approx_unchecked_to)]
///
/// let value = 4.6_f32;
/// let rounded = unsafe { value.approx_unchecked_to::<u16>() };
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
/// assert_eq!(rounded, 4);
///
/// let value = -128.9_f32;
/// let rounded = unsafe { value.approx_unchecked_to::<i8>() };
/// assert_eq!(rounded, std::i8::MIN);
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
/// assert_eq!(rounded, i8::MIN);
/// ```
///
/// # Safety
@ -496,13 +494,13 @@ impl f64 {
/// * Not be `NaN`
/// * Not be infinite
/// * Be representable in the return type `Int`, after truncating off its fractional part
#[unstable(feature = "float_approx_unchecked_to", issue = "67058")]
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
#[inline]
pub unsafe fn approx_unchecked_to<Int>(self) -> Int
pub unsafe fn to_int_unchecked<Int>(self) -> Int
where
Self: FloatToInt<Int>,
{
FloatToInt::<Int>::approx_unchecked(self)
FloatToInt::<Int>::to_int_unchecked(self)
}
/// Raw transmutation to `u64`.

View File

@ -174,7 +174,7 @@ NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
/// let zero = Wrapping(0u32);
/// let one = Wrapping(1u32);
///
/// assert_eq!(std::u32::MAX, (zero - one).0);
/// assert_eq!(u32::MAX, (zero - one).0);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
@ -4376,7 +4376,7 @@ impl u8 {
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_uppercase(&self) -> u8 {
// Unset the fith bit if this is a lowercase letter
// Unset the fifth bit if this is a lowercase letter
*self & !((self.is_ascii_lowercase() as u8) << 5)
}
@ -4399,7 +4399,7 @@ impl u8 {
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
#[inline]
pub fn to_ascii_lowercase(&self) -> u8 {
// Set the fith bit if this is an uppercase letter
// Set the fifth bit if this is an uppercase letter
*self | ((self.is_ascii_uppercase() as u8) << 5)
}

View File

@ -139,10 +139,9 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// ```
/// #![feature(range_is_empty)]
///
/// use std::f32::NAN;
/// assert!(!(3.0..5.0).is_empty());
/// assert!( (3.0..NAN).is_empty());
/// assert!( (NAN..5.0).is_empty());
/// assert!( (3.0..f32::NAN).is_empty());
/// assert!( (f32::NAN..5.0).is_empty());
/// ```
#[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
pub fn is_empty(&self) -> bool {
@ -496,10 +495,9 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// ```
/// #![feature(range_is_empty)]
///
/// use std::f32::NAN;
/// assert!(!(3.0..=5.0).is_empty());
/// assert!( (3.0..=NAN).is_empty());
/// assert!( (NAN..=5.0).is_empty());
/// assert!( (3.0..=f32::NAN).is_empty());
/// assert!( (f32::NAN..=5.0).is_empty());
/// ```
///
/// This method returns `true` after iteration has finished:

View File

@ -659,8 +659,8 @@ impl<T: ?Sized> *const T {
/// `align`.
///
/// If it is not possible to align the pointer, the implementation returns
/// `usize::max_value()`. It is permissible for the implementation to *always*
/// return `usize::max_value()`. Only your algorithm's performance can depend
/// `usize::MAX`. It is permissible for the implementation to *always*
/// return `usize::MAX`. Only your algorithm's performance can depend
/// on getting a usable offset here, not its correctness.
///
/// The offset is expressed in number of `T` elements, and not bytes. The value returned can be

View File

@ -847,8 +847,8 @@ impl<T: ?Sized> *mut T {
/// `align`.
///
/// If it is not possible to align the pointer, the implementation returns
/// `usize::max_value()`. It is permissible for the implementation to *always*
/// return `usize::max_value()`. Only your algorithm's performance can depend
/// `usize::MAX`. It is permissible for the implementation to *always*
/// return `usize::MAX`. Only your algorithm's performance can depend
/// on getting a usable offset here, not its correctness.
///
/// The offset is expressed in number of `T` elements, and not bytes. The value returned can be

View File

@ -6,7 +6,8 @@
//! They can be used as targets of transmutes in unsafe code for manipulating
//! the raw representations directly.
//!
//! Their definition should always match the ABI defined in `rustc::back::abi`.
//! Their definition should always match the ABI defined in
//! `rustc_middle::ty::layout`.
/// The representation of a trait object like `&SomeTrait`.
///

View File

@ -2588,7 +2588,7 @@ impl<T> [T] {
/// assert!(![1, 3, 2, 4].is_sorted());
/// assert!([0].is_sorted());
/// assert!(empty.is_sorted());
/// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
/// assert!(![0.0, 1.0, f32::NAN].is_sorted());
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]

View File

@ -9,7 +9,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use self::pattern::Pattern;
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, SearchStep, Searcher};
use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
use crate::char;
use crate::fmt::{self, Write};
@ -2642,7 +2642,7 @@ impl str {
/// # Panics
///
/// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
/// beyond the last code point of the string slice.
/// past the end of the last code point of the string slice.
///
/// # Examples
///
@ -2683,7 +2683,7 @@ impl str {
/// # Panics
///
/// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
/// beyond the last code point of the string slice.
/// past the end of the last code point of the string slice.
///
/// # Examples
///
@ -3986,26 +3986,15 @@ impl str {
/// ```
/// #![feature(str_strip)]
///
/// assert_eq!("foobar".strip_prefix("foo"), Some("bar"));
/// assert_eq!("foobar".strip_prefix("bar"), None);
/// assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar"));
/// assert_eq!("foo:bar".strip_prefix("bar"), None);
/// assert_eq!("foofoo".strip_prefix("foo"), Some("foo"));
/// ```
#[must_use = "this returns the remaining substring as a new slice, \
without modifying the original"]
#[unstable(feature = "str_strip", reason = "newly added", issue = "67302")]
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
let mut matcher = prefix.into_searcher(self);
if let SearchStep::Match(start, len) = matcher.next() {
debug_assert_eq!(
start, 0,
"The first search step from Searcher \
must include the first character"
);
// SAFETY: `Searcher` is known to return valid indices.
unsafe { Some(self.get_unchecked(len..)) }
} else {
None
}
prefix.strip_prefix_of(self)
}
/// Returns a string slice with the suffix removed.
@ -4020,8 +4009,8 @@ impl str {
///
/// ```
/// #![feature(str_strip)]
/// assert_eq!("barfoo".strip_suffix("foo"), Some("bar"));
/// assert_eq!("barfoo".strip_suffix("bar"), None);
/// assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar"));
/// assert_eq!("bar:foo".strip_suffix("bar"), None);
/// assert_eq!("foofoo".strip_suffix("foo"), Some("foo"));
/// ```
#[must_use = "this returns the remaining substring as a new slice, \
@ -4032,19 +4021,7 @@ impl str {
P: Pattern<'a>,
<P as Pattern<'a>>::Searcher: ReverseSearcher<'a>,
{
let mut matcher = suffix.into_searcher(self);
if let SearchStep::Match(start, end) = matcher.next_back() {
debug_assert_eq!(
end,
self.len(),
"The first search step from ReverseSearcher \
must include the last character"
);
// SAFETY: `Searcher` is known to return valid indices.
unsafe { Some(self.get_unchecked(..start)) }
} else {
None
}
suffix.strip_suffix_of(self)
}
/// Returns a string slice with all suffixes that match a pattern

View File

@ -47,6 +47,22 @@ pub trait Pattern<'a>: Sized {
matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
}
/// Removes the pattern from the front of haystack, if it matches.
#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
if let SearchStep::Match(start, len) = self.into_searcher(haystack).next() {
debug_assert_eq!(
start, 0,
"The first search step from Searcher \
must include the first character"
);
// SAFETY: `Searcher` is known to return valid indices.
unsafe { Some(haystack.get_unchecked(len..)) }
} else {
None
}
}
/// Checks whether the pattern matches at the back of the haystack
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool
@ -55,6 +71,26 @@ pub trait Pattern<'a>: Sized {
{
matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
}
/// Removes the pattern from the back of haystack, if it matches.
#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
where
Self::Searcher: ReverseSearcher<'a>,
{
if let SearchStep::Match(start, end) = self.into_searcher(haystack).next_back() {
debug_assert_eq!(
end,
haystack.len(),
"The first search step from ReverseSearcher \
must include the last character"
);
// SAFETY: `Searcher` is known to return valid indices.
unsafe { Some(haystack.get_unchecked(..start)) }
} else {
None
}
}
}
// Searcher
@ -448,6 +484,11 @@ impl<'a> Pattern<'a> for char {
self.encode_utf8(&mut [0u8; 4]).is_prefix_of(haystack)
}
#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
self.encode_utf8(&mut [0u8; 4]).strip_prefix_of(haystack)
}
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool
where
@ -455,6 +496,14 @@ impl<'a> Pattern<'a> for char {
{
self.encode_utf8(&mut [0u8; 4]).is_suffix_of(haystack)
}
#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
where
Self::Searcher: ReverseSearcher<'a>,
{
self.encode_utf8(&mut [0u8; 4]).strip_suffix_of(haystack)
}
}
/////////////////////////////////////////////////////////////////////////////
@ -569,6 +618,11 @@ macro_rules! pattern_methods {
($pmap)(self).is_prefix_of(haystack)
}
#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
($pmap)(self).strip_prefix_of(haystack)
}
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool
where
@ -576,6 +630,14 @@ macro_rules! pattern_methods {
{
($pmap)(self).is_suffix_of(haystack)
}
#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
where
$t: ReverseSearcher<'a>,
{
($pmap)(self).strip_suffix_of(haystack)
}
};
}
@ -715,11 +777,34 @@ impl<'a, 'b> Pattern<'a> for &'b str {
haystack.as_bytes().starts_with(self.as_bytes())
}
/// Removes the pattern from the front of haystack, if it matches.
#[inline]
fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
if self.is_prefix_of(haystack) {
// SAFETY: prefix was just verified to exist.
unsafe { Some(haystack.get_unchecked(self.as_bytes().len()..)) }
} else {
None
}
}
/// Checks whether the pattern matches at the back of the haystack
#[inline]
fn is_suffix_of(self, haystack: &'a str) -> bool {
haystack.as_bytes().ends_with(self.as_bytes())
}
/// Removes the pattern from the back of haystack, if it matches.
#[inline]
fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str> {
if self.is_suffix_of(haystack) {
let i = haystack.len() - self.as_bytes().len();
// SAFETY: suffix was just verified to exist.
unsafe { Some(haystack.get_unchecked(..i)) }
} else {
None
}
}
}
/////////////////////////////////////////////////////////////////////////////

View File

@ -389,7 +389,7 @@ impl Duration {
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
/// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
/// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
@ -460,7 +460,7 @@ impl Duration {
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
/// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
/// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]

View File

@ -1,132 +0,0 @@
/// This declares a list of types which can be allocated by `Arena`.
///
/// The `few` modifier will cause allocation to use the shared arena and recording the destructor.
/// This is faster and more memory efficient if there's only a few allocations of the type.
/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is
/// faster and more memory efficient if there is lots of allocations.
///
/// Specifying the `decode` modifier will add decode impls for &T and &[T] where T is the type
/// listed. These impls will appear in the implement_ty_decoder! macro.
#[macro_export]
macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
[] layouts: rustc::ty::layout::Layout,
[] generics: rustc::ty::Generics,
[] trait_def: rustc::ty::TraitDef,
[] adt_def: rustc::ty::AdtDef,
[] steal_mir: rustc::ty::steal::Steal<rustc::mir::BodyAndCache<$tcx>>,
[] mir: rustc::mir::BodyAndCache<$tcx>,
[] steal_promoted: rustc::ty::steal::Steal<
rustc_index::vec::IndexVec<
rustc::mir::Promoted,
rustc::mir::BodyAndCache<$tcx>
>
>,
[] promoted: rustc_index::vec::IndexVec<
rustc::mir::Promoted,
rustc::mir::BodyAndCache<$tcx>
>,
[decode] tables: rustc::ty::TypeckTables<$tcx>,
[decode] borrowck_result: rustc::mir::BorrowCheckResult<$tcx>,
[] const_allocs: rustc::mir::interpret::Allocation,
[] vtable_method: Option<(
rustc_hir::def_id::DefId,
rustc::ty::subst::SubstsRef<$tcx>
)>,
[few, decode] mir_keys: rustc_hir::def_id::DefIdSet,
[decode] specialization_graph: rustc::traits::specialization_graph::Graph,
[] region_scope_tree: rustc::middle::region::ScopeTree,
[] item_local_set: rustc_hir::ItemLocalSet,
[decode] mir_const_qualif: rustc_index::bit_set::BitSet<rustc::mir::Local>,
[] trait_impls_of: rustc::ty::trait_def::TraitImpls,
[] associated_items: rustc::ty::AssociatedItems,
[] dropck_outlives:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx,
rustc::traits::query::DropckOutlivesResult<'tcx>
>
>,
[] normalize_projection_ty:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx,
rustc::traits::query::NormalizationResult<'tcx>
>
>,
[] implied_outlives_bounds:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx,
Vec<rustc::traits::query::OutlivesBound<'tcx>>
>
>,
[] type_op_subtype:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx, ()>
>,
[] type_op_normalize_poly_fn_sig:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::PolyFnSig<'tcx>>
>,
[] type_op_normalize_fn_sig:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::FnSig<'tcx>>
>,
[] type_op_normalize_predicate:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::Predicate<'tcx>>
>,
[] type_op_normalize_ty:
rustc::infer::canonical::Canonical<'tcx,
rustc::infer::canonical::QueryResponse<'tcx, rustc::ty::Ty<'tcx>>
>,
[few] crate_inherent_impls: rustc::ty::CrateInherentImpls,
[few] upstream_monomorphizations:
rustc_hir::def_id::DefIdMap<
rustc_data_structures::fx::FxHashMap<
rustc::ty::subst::SubstsRef<'tcx>,
rustc_hir::def_id::CrateNum
>
>,
[few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
rustc_span::symbol::Symbol,
rustc_hir::def_id::DefId,
>,
[few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes,
[few] lint_levels: rustc::lint::LintLevelMap,
[few] stability_index: rustc::middle::stability::Index<'tcx>,
[few] features: rustc_feature::Features,
[few] all_traits: Vec<rustc_hir::def_id::DefId>,
[few] privacy_access_levels: rustc::middle::privacy::AccessLevels,
[few] target_features_whitelist: rustc_data_structures::fx::FxHashMap<
String,
Option<rustc_span::symbol::Symbol>
>,
[few] wasm_import_module_map: rustc_data_structures::fx::FxHashMap<
rustc_hir::def_id::DefId,
String
>,
[few] get_lib_features: rustc::middle::lib_features::LibFeatures,
[few] defined_lib_features: rustc::middle::lang_items::LanguageItems,
[few] visible_parent_map: rustc_hir::def_id::DefIdMap<rustc_hir::def_id::DefId>,
[few] foreign_module: rustc::middle::cstore::ForeignModule,
[few] foreign_modules: Vec<rustc::middle::cstore::ForeignModule>,
[few] reachable_non_generics: rustc_hir::def_id::DefIdMap<
rustc::middle::exported_symbols::SymbolExportLevel
>,
[few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
[few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
[] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
// Interned types
[] tys: rustc::ty::TyS<$tcx>,
// HIR query types
[few] indexed_hir: rustc::hir::map::IndexedHir<$tcx>,
[few] hir_definitions: rustc_hir::definitions::Definitions,
[] hir_owner: rustc::hir::Owner<$tcx>,
[] hir_owner_nodes: rustc::hir::OwnerNodes<$tcx>,
], $tcx);
)
}
arena_types!(arena::declare_arena, [], 'tcx);

View File

@ -10,7 +10,7 @@ pub enum EntryPointType {
OtherMain, // Not an entry point, but some other function named main
}
// Beware, this is duplicated in librustc/middle/entry.rs, make sure to keep
// Beware, this is duplicated in librustc_middle/middle/entry.rs, make sure to keep
// them in sync.
pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
match item.kind {

View File

@ -1,4 +1,4 @@
//! Definitions shared by macros / syntax extensions and e.g. librustc.
//! Definitions shared by macros / syntax extensions and e.g. librustc_middle.
use crate::ast::Attribute;
use rustc_span::symbol::sym;

View File

@ -54,7 +54,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in librustc.
/// instead of implementing everything in librustc_middle.
pub trait HashStableContext: rustc_span::HashStableContext {
fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
}

View File

@ -972,8 +972,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
) -> hir::BodyId {
let prev_gen_kind = self.generator_kind.take();
let task_context = self.task_context.take();
let (parameters, result) = f(self);
let body_id = self.record_body(parameters, result);
self.task_context = task_context;
self.generator_kind = prev_gen_kind;
body_id
}
@ -1332,17 +1334,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.resolver.definitions().as_local_node_id(def_id)
{
for param in &generics.params {
match param.kind {
GenericParamKind::Type { .. } => {
if node_id == param.id {
add_bounds
.entry(param.id)
.or_default()
.push(bound.clone());
continue 'next_bound;
}
if let GenericParamKind::Type { .. } = param.kind {
if node_id == param.id {
add_bounds
.entry(param.id)
.or_default()
.push(bound.clone());
continue 'next_bound;
}
_ => {}
}
}
}

View File

@ -97,7 +97,7 @@ struct LoweringContext<'a, 'hir: 'a> {
/// HACK(Centril): there is a cyclic dependency between the parser and lowering
/// if we don't have this function pointer. To avoid that dependency so that
/// librustc is independent of the parser, we use dynamic dispatch here.
/// librustc_middle is independent of the parser, we use dynamic dispatch here.
nt_to_tokenstream: NtToTokenstream,
/// Used to allocate HIR nodes

View File

@ -516,27 +516,25 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
fn visit_generic_param(&mut self, param: &'a GenericParam) {
match param.kind {
GenericParamKind::Const { .. } => gate_feature_post!(
if let GenericParamKind::Const { .. } = param.kind {
gate_feature_post!(
&self,
const_generics,
param.ident.span,
"const generics are unstable"
),
_ => {}
)
}
visit::walk_generic_param(self, param)
}
fn visit_assoc_ty_constraint(&mut self, constraint: &'a AssocTyConstraint) {
match constraint.kind {
AssocTyConstraintKind::Bound { .. } => gate_feature_post!(
if let AssocTyConstraintKind::Bound { .. } = constraint.kind {
gate_feature_post!(
&self,
associated_type_bounds,
constraint.span,
"associated type bounds are unstable"
),
_ => {}
)
}
visit::walk_assoc_ty_constraint(self, constraint)
}

View File

@ -637,9 +637,8 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
match tt {
TokenTree::Token(ref token) => {
self.word(token_to_string_ext(&token, convert_dollar_crate));
match token.kind {
token::DocComment(..) => self.hardbreak(),
_ => {}
if let token::DocComment(..) = token.kind {
self.hardbreak()
}
}
TokenTree::Delimited(dspan, delim, tts) => {
@ -1390,13 +1389,10 @@ impl<'a> State<'a> {
self.print_visibility(&v.vis);
let generics = ast::Generics::default();
self.print_struct(&v.data, &generics, v.ident, v.span, false);
match v.disr_expr {
Some(ref d) => {
self.s.space();
self.word_space("=");
self.print_expr(&d.value)
}
_ => {}
if let Some(ref d) = v.disr_expr {
self.s.space();
self.word_space("=");
self.print_expr(&d.value)
}
}
@ -2082,12 +2078,10 @@ impl<'a> State<'a> {
}
ast::ExprKind::Yield(ref e) => {
self.s.word("yield");
match *e {
Some(ref expr) => {
self.s.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
_ => (),
if let Some(ref expr) = *e {
self.s.space();
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
ast::ExprKind::Try(ref e) => {
@ -2139,9 +2133,8 @@ impl<'a> State<'a> {
self.s.word("::");
let item_segment = path.segments.last().unwrap();
self.print_ident(item_segment.ident);
match item_segment.args {
Some(ref args) => self.print_generic_args(args, colons_before_params),
None => {}
if let Some(ref args) = item_segment.args {
self.print_generic_args(args, colons_before_params)
}
}

View File

@ -870,7 +870,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
if literal.is_power_of_two() {
// rustc::ty::layout::Align restricts align to <= 2^29
// rustc_middle::ty::layout::Align restricts align to <= 2^29
if *literal <= 1 << 29 {
Ok(*literal as u32)
} else {

View File

@ -27,11 +27,8 @@ pub mod printf {
}
pub fn set_position(&mut self, start: usize, end: usize) {
match self {
Substitution::Format(ref mut fmt) => {
fmt.position = InnerSpan::new(start, end);
}
_ => {}
if let Substitution::Format(ref mut fmt) = self {
fmt.position = InnerSpan::new(start, end);
}
}
@ -311,9 +308,8 @@ pub mod printf {
let at = {
let start = s.find('%')?;
match s[start + 1..].chars().next()? {
'%' => return Some((Substitution::Escape, &s[start + 2..])),
_ => { /* fall-through */ }
if let '%' = s[start + 1..].chars().next()? {
return Some((Substitution::Escape, &s[start + 2..]));
}
Cur::new_at(&s[..], start)

View File

@ -16,7 +16,7 @@ flate2 = "1.0"
libc = "0.2"
measureme = "0.7.1"
log = "0.4"
rustc = { path = "../librustc" }
rustc_middle = { path = "../librustc_middle" }
rustc-demangle = "0.1"
rustc_attr = { path = "../librustc_attr" }
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }

View File

@ -4,4 +4,4 @@ that runs towards the end of the compilation process.
For more information about how codegen works, see the [rustc dev guide].
[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/codegen.html
[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/backend/codegen.html

View File

@ -5,22 +5,20 @@ use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use rustc::bug;
use rustc::ty::layout::{self};
use rustc::ty::Ty;
use rustc_codegen_ssa::mir::operand::OperandValue;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::MemFlags;
use rustc_middle::bug;
pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
use rustc_middle::ty::Ty;
use rustc_target::abi::call::ArgAbi;
use rustc_target::abi::{HasDataLayout, LayoutOf};
pub use rustc_target::abi::call::*;
use rustc_target::abi::{self, HasDataLayout, Int, LayoutOf};
pub use rustc_target::spec::abi::Abi;
use libc::c_uint;
pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
pub use rustc_target::abi::call::*;
pub use rustc_target::spec::abi::Abi;
macro_rules! for_each_kind {
($flags: ident, $f: ident, $($kind: ident),+) => ({
$(if $flags.contains(ArgAttribute::$kind) { $f(llvm::Attribute::$kind) })+
@ -396,6 +394,11 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn);
}
// FIXME(eddyb, wesleywiser): apply this to callsites as well?
if !self.can_unwind {
llvm::Attribute::NoUnwind.apply_llfn(llvm::AttributePlace::Function, llfn);
}
let mut i = 0;
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
@ -431,6 +434,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
// FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
let mut i = 0;
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
@ -443,11 +448,11 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
_ => {}
}
if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi {
if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
// If the value is a boolean, the range is 0..2 and that ultimately
// become 0..0 when the type becomes i1, which would be rejected
// by the LLVM verifier.
if let layout::Int(..) = scalar.value {
if let Int(..) = scalar.value {
if !scalar.is_bool() {
let range = scalar.valid_range_exclusive(bx);
if range.start != range.end {

View File

@ -1,8 +1,8 @@
use crate::attributes;
use libc::c_uint;
use rustc::bug;
use rustc::ty::TyCtxt;
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use crate::llvm::{self, False, True};
use crate::ModuleLlvm;

View File

@ -2,21 +2,18 @@
use std::ffi::CString;
use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc::ty::layout::HasTyCtxt;
use rustc::ty::query::Providers;
use rustc::ty::{self, Ty, TyCtxt};
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::const_cstr;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::config::{OptLevel, Sanitizer};
use rustc_session::Session;
use rustc_target::abi::call::Conv;
use rustc_target::spec::PanicStrategy;
use crate::abi::FnAbi;
use crate::attributes;
use crate::llvm::AttributePlace::Function;
use crate::llvm::{self, Attribute};
@ -77,12 +74,6 @@ pub fn emit_uwtable(val: &'ll Value, emit: bool) {
Attribute::UWTable.toggle_llfn(Function, val, emit);
}
/// Tell LLVM whether the function can or cannot unwind.
#[inline]
fn unwind(val: &'ll Value, can_unwind: bool) {
Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind);
}
/// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue.
#[inline]
fn naked(val: &'ll Value, is_naked: bool) {
@ -246,12 +237,7 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) {
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
/// attributes.
pub fn from_fn_attrs(
cx: &CodegenCx<'ll, 'tcx>,
llfn: &'ll Value,
instance: ty::Instance<'tcx>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) {
pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>) {
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
match codegen_fn_attrs.optimize {
@ -315,46 +301,6 @@ pub fn from_fn_attrs(
}
sanitize(cx, codegen_fn_attrs.flags, llfn);
unwind(
llfn,
if cx.tcx.sess.panic_strategy() != PanicStrategy::Unwind {
// In panic=abort mode we assume nothing can unwind anywhere, so
// optimize based on this!
false
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) {
// If a specific #[unwind] attribute is present, use that.
true
} else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
// Special attribute for allocator functions, which can't unwind.
false
} else {
if fn_abi.conv == Conv::Rust {
// Any Rust method (or `extern "Rust" fn` or `extern
// "rust-call" fn`) is explicitly allowed to unwind
// (unless it has no-unwind attribute, handled above).
true
} else {
// Anything else is either:
//
// 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or
//
// 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`).
//
// Foreign items (case 1) are assumed to not unwind; it is
// UB otherwise. (At least for now; see also
// rust-lang/rust#63909 and Rust RFC 2753.)
//
// Items defined in Rust with non-Rust ABIs (case 2) are also
// not supposed to unwind. Whether this should be enforced
// (versus stating it is UB) and *how* it would be enforced
// is currently under discussion; see rust-lang/rust#58794.
//
// In either case, we mark item as explicitly nounwind.
false
}
},
);
// Always annotate functions with the target-cpu they are compiled for.
// Without this, ThinLTO won't inline Rust functions into Clang generated
// functions (because Clang annotates functions this way too).

View File

@ -6,9 +6,6 @@ use crate::llvm::archive_ro::ArchiveRO;
use crate::llvm::{self, False, True};
use crate::{LlvmCodegenBackend, ModuleLlvm};
use log::{debug, info};
use rustc::bug;
use rustc::dep_graph::WorkProduct;
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
@ -17,6 +14,9 @@ use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{FatalError, Handler};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::exported_symbols::SymbolExportLevel;
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, Lto};

View File

@ -14,8 +14,6 @@ use crate::type_::Type;
use crate::LlvmCodegenBackend;
use crate::ModuleLlvm;
use log::debug;
use rustc::bug;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, RLIB_BYTECODE_EXTENSION};
@ -23,6 +21,8 @@ use rustc_data_structures::small_c_str::SmallCStr;
use rustc_errors::{FatalError, Handler};
use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
use rustc_session::Session;

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