mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
Merge branch 'master' into abi
This commit is contained in:
commit
aa223304dc
2
.github/ISSUE_TEMPLATE/ice.md
vendored
2
.github/ISSUE_TEMPLATE/ice.md
vendored
@ -14,7 +14,7 @@ http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
|
||||
|
||||
### Code
|
||||
|
||||
```
|
||||
```Rust
|
||||
<code>
|
||||
```
|
||||
|
||||
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -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:
|
||||
|
110
Cargo.lock
110
Cargo.lock
@ -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",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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));
|
||||
|
@ -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" {
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 *);
|
||||
|
@ -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
|
||||
|
@ -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++ \
|
||||
|
6
src/ci/docker/dist-various-1/install-aarch64-none-elf.sh
Executable file
6
src/ci/docker/dist-various-1/install-aarch64-none-elf.sh
Executable 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
|
@ -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
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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/)
|
||||
|
@ -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),
|
||||
|
@ -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)]
|
||||
|
@ -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}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -1,3 +1,4 @@
|
||||
#![feature(btree_drain_filter)]
|
||||
#![feature(map_first_last)]
|
||||
#![feature(repr_simd)]
|
||||
#![feature(test)]
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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)
|
||||
);
|
||||
|
@ -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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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));
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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")]
|
||||
|
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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)]
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
1043
src/libcore/alloc.rs
1043
src/libcore/alloc.rs
File diff suppressed because it is too large
Load Diff
198
src/libcore/alloc/global.rs
Normal file
198
src/libcore/alloc/global.rs
Normal 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 library’s 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
346
src/libcore/alloc/layout.rs
Normal 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
367
src/libcore/alloc/mod.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
@ -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 {}
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ mod private {
|
||||
/// Typically doesn’t 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
@ -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");
|
||||
///
|
||||
|
@ -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")]
|
||||
|
@ -1582,8 +1582,16 @@ extern "rust-intrinsic" {
|
||||
/// Convert with LLVM’s 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 LLVM’s 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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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`.
|
||||
|
@ -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`.
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
///
|
||||
|
@ -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")]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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]
|
||||
|
@ -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);
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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" }
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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).
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user