mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #135959 - matthiaskrgr:rollup-0jenyfw, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #135366 (Enable `unreachable_pub` lint in `test` and `proc_macro` crates) - #135638 (Make it possible to build GCC on CI) - #135648 (support wasm inline assembly in `naked_asm!`) - #135827 (CI: free disk with in-tree script instead of GitHub Action) - #135855 (Only assert the `Parser` size on specific arches) - #135878 (ci: use 8 core arm runner for dist-aarch64-linux) - #135905 (Enable kernel sanitizers for aarch64-unknown-none-softfloat) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
48ef38d350
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -109,7 +109,7 @@ jobs:
|
||||
# intensive jobs to run on free runners, which however also have
|
||||
# less disk space.
|
||||
- name: free up disk space
|
||||
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
|
||||
run: src/ci/scripts/free-disk-space.sh
|
||||
if: matrix.free_disk
|
||||
|
||||
# Rust Log Analyzer can't currently detect the PR number of a GitHub
|
||||
|
@ -1,10 +1,14 @@
|
||||
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
|
||||
use rustc_attr_parsing::InstructionSetAttr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
|
||||
use rustc_middle::mir::{Body, InlineAsmOperand};
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{Instance, TyCtxt};
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
|
||||
use rustc_middle::ty::{Instance, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug, ty};
|
||||
use rustc_span::sym;
|
||||
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
|
||||
use rustc_target::spec::WasmCAbi;
|
||||
|
||||
use crate::common;
|
||||
use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
|
||||
@ -32,7 +36,8 @@ pub(crate) fn codegen_naked_asm<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
||||
let item_data = cx.codegen_unit().items().get(&MonoItem::Fn(instance)).unwrap();
|
||||
let name = cx.mangled_name(instance);
|
||||
let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data);
|
||||
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
|
||||
let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data, fn_abi);
|
||||
|
||||
let mut template_vec = Vec::new();
|
||||
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin.into()));
|
||||
@ -103,6 +108,7 @@ enum AsmBinaryFormat {
|
||||
Elf,
|
||||
Macho,
|
||||
Coff,
|
||||
Wasm,
|
||||
}
|
||||
|
||||
impl AsmBinaryFormat {
|
||||
@ -111,6 +117,8 @@ impl AsmBinaryFormat {
|
||||
Self::Coff
|
||||
} else if target.is_like_osx {
|
||||
Self::Macho
|
||||
} else if target.is_like_wasm {
|
||||
Self::Wasm
|
||||
} else {
|
||||
Self::Elf
|
||||
}
|
||||
@ -122,6 +130,7 @@ fn prefix_and_suffix<'tcx>(
|
||||
instance: Instance<'tcx>,
|
||||
asm_name: &str,
|
||||
item_data: &MonoItemData,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
) -> (String, String) {
|
||||
use std::fmt::Write;
|
||||
|
||||
@ -169,7 +178,7 @@ fn prefix_and_suffix<'tcx>(
|
||||
}
|
||||
Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => {
|
||||
match asm_binary_format {
|
||||
AsmBinaryFormat::Elf | AsmBinaryFormat::Coff => {
|
||||
AsmBinaryFormat::Elf | AsmBinaryFormat::Coff | AsmBinaryFormat::Wasm => {
|
||||
writeln!(w, ".weak {asm_name}")?;
|
||||
}
|
||||
AsmBinaryFormat::Macho => {
|
||||
@ -264,7 +273,161 @@ fn prefix_and_suffix<'tcx>(
|
||||
writeln!(end, "{}", arch_suffix).unwrap();
|
||||
}
|
||||
}
|
||||
AsmBinaryFormat::Wasm => {
|
||||
let section = link_section.unwrap_or(format!(".text.{asm_name}"));
|
||||
|
||||
writeln!(begin, ".section {section},\"\",@").unwrap();
|
||||
// wasm functions cannot be aligned, so skip
|
||||
write_linkage(&mut begin).unwrap();
|
||||
if let Visibility::Hidden = item_data.visibility {
|
||||
writeln!(begin, ".hidden {asm_name}").unwrap();
|
||||
}
|
||||
writeln!(begin, ".type {asm_name}, @function").unwrap();
|
||||
if !arch_prefix.is_empty() {
|
||||
writeln!(begin, "{}", arch_prefix).unwrap();
|
||||
}
|
||||
writeln!(begin, "{asm_name}:").unwrap();
|
||||
writeln!(
|
||||
begin,
|
||||
".functype {asm_name} {}",
|
||||
wasm_functype(tcx, fn_abi, instance.def_id())
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
writeln!(end).unwrap();
|
||||
// .size is ignored for function symbols, so we can skip it
|
||||
writeln!(end, "end_function").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
(begin, end)
|
||||
}
|
||||
|
||||
/// The webassembly type signature for the given function.
|
||||
///
|
||||
/// Used by the `.functype` directive on wasm targets.
|
||||
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String {
|
||||
let mut signature = String::with_capacity(64);
|
||||
|
||||
let ptr_type = match tcx.data_layout.pointer_size.bits() {
|
||||
32 => "i32",
|
||||
64 => "i64",
|
||||
other => bug!("wasm pointer size cannot be {other} bits"),
|
||||
};
|
||||
|
||||
// FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
|
||||
// please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
|
||||
// basically the commit introducing this comment should be reverted
|
||||
if let PassMode::Pair { .. } = fn_abi.ret.mode {
|
||||
let _ = WasmCAbi::Legacy;
|
||||
span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
|
||||
);
|
||||
}
|
||||
|
||||
let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
|
||||
|
||||
signature.push('(');
|
||||
|
||||
if hidden_return {
|
||||
signature.push_str(ptr_type);
|
||||
if !fn_abi.args.is_empty() {
|
||||
signature.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
let mut it = fn_abi.args.iter().peekable();
|
||||
while let Some(arg_abi) = it.next() {
|
||||
wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id);
|
||||
if it.peek().is_some() {
|
||||
signature.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
signature.push_str(") -> (");
|
||||
|
||||
if !hidden_return {
|
||||
wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id);
|
||||
}
|
||||
|
||||
signature.push(')');
|
||||
|
||||
signature
|
||||
}
|
||||
|
||||
fn wasm_type<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
signature: &mut String,
|
||||
arg_abi: &ArgAbi<'_, Ty<'tcx>>,
|
||||
ptr_type: &'static str,
|
||||
def_id: DefId,
|
||||
) {
|
||||
match arg_abi.mode {
|
||||
PassMode::Ignore => { /* do nothing */ }
|
||||
PassMode::Direct(_) => {
|
||||
let direct_type = match arg_abi.layout.backend_repr {
|
||||
BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
|
||||
BackendRepr::Vector { .. } => "v128",
|
||||
BackendRepr::Memory { .. } => {
|
||||
// FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
|
||||
let _ = WasmCAbi::Legacy;
|
||||
span_bug!(
|
||||
tcx.def_span(def_id),
|
||||
"cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
|
||||
);
|
||||
}
|
||||
other => unreachable!("unexpected BackendRepr: {:?}", other),
|
||||
};
|
||||
|
||||
signature.push_str(direct_type);
|
||||
}
|
||||
PassMode::Pair(_, _) => match arg_abi.layout.backend_repr {
|
||||
BackendRepr::ScalarPair(a, b) => {
|
||||
signature.push_str(wasm_primitive(a.primitive(), ptr_type));
|
||||
signature.push_str(", ");
|
||||
signature.push_str(wasm_primitive(b.primitive(), ptr_type));
|
||||
}
|
||||
other => unreachable!("{other:?}"),
|
||||
},
|
||||
PassMode::Cast { pad_i32, ref cast } => {
|
||||
// For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);`
|
||||
assert!(!pad_i32, "not currently used by wasm calling convention");
|
||||
assert!(cast.prefix[0].is_none(), "no prefix");
|
||||
assert_eq!(cast.rest.total, arg_abi.layout.size, "single item");
|
||||
|
||||
let wrapped_wasm_type = match cast.rest.unit.kind {
|
||||
RegKind::Integer => match cast.rest.unit.size.bytes() {
|
||||
..=4 => "i32",
|
||||
..=8 => "i64",
|
||||
_ => ptr_type,
|
||||
},
|
||||
RegKind::Float => match cast.rest.unit.size.bytes() {
|
||||
..=4 => "f32",
|
||||
..=8 => "f64",
|
||||
_ => ptr_type,
|
||||
},
|
||||
RegKind::Vector => "v128",
|
||||
};
|
||||
|
||||
signature.push_str(wrapped_wasm_type);
|
||||
}
|
||||
PassMode::Indirect { .. } => signature.push_str(ptr_type),
|
||||
}
|
||||
}
|
||||
|
||||
fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str {
|
||||
match primitive {
|
||||
Primitive::Int(integer, _) => match integer {
|
||||
Integer::I8 | Integer::I16 | Integer::I32 => "i32",
|
||||
Integer::I64 => "i64",
|
||||
Integer::I128 => "i64, i64",
|
||||
},
|
||||
Primitive::Float(float) => match float {
|
||||
Float::F16 | Float::F32 => "f32",
|
||||
Float::F64 => "f64",
|
||||
Float::F128 => "i64, i64",
|
||||
},
|
||||
Primitive::Pointer(_) => ptr_type,
|
||||
}
|
||||
}
|
||||
|
@ -189,8 +189,9 @@ pub struct Parser<'a> {
|
||||
}
|
||||
|
||||
// This type is used a lot, e.g. it's cloned when matching many declarative macro rules with
|
||||
// nonterminals. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(all(target_pointer_width = "64", not(target_arch = "s390x")))]
|
||||
// nonterminals. Make sure it doesn't unintentionally get bigger. We only check a few arches
|
||||
// though, because `TokenTypeSet(u128)` alignment varies on others, changing the total size.
|
||||
#[cfg(all(target_pointer_width = "64", any(target_arch = "aarch64", target_arch = "x86_64")))]
|
||||
rustc_data_structures::static_assert_size!(Parser<'_>, 288);
|
||||
|
||||
/// Stores span information about a closure.
|
||||
|
@ -7,7 +7,8 @@
|
||||
// For example, `-C target-cpu=cortex-a53`.
|
||||
|
||||
use crate::spec::{
|
||||
Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, StackProbeType, Target, TargetOptions,
|
||||
Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target,
|
||||
TargetOptions,
|
||||
};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
@ -19,6 +20,7 @@ pub(crate) fn target() -> Target {
|
||||
relocation_model: RelocModel::Static,
|
||||
disable_redzone: true,
|
||||
max_atomic_width: Some(128),
|
||||
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
|
||||
stack_probes: StackProbeType::Inline,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
..Default::default()
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Closure<'a, A, R> {
|
||||
pub(super) struct Closure<'a, A, R> {
|
||||
call: unsafe extern "C" fn(*mut Env, A) -> R,
|
||||
env: *mut Env,
|
||||
// Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing
|
||||
@ -26,7 +26,7 @@ impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> {
|
||||
}
|
||||
|
||||
impl<'a, A, R> Closure<'a, A, R> {
|
||||
pub fn call(&mut self, arg: A) -> R {
|
||||
pub(super) fn call(&mut self, arg: A) -> R {
|
||||
unsafe { (self.call)(self.env, arg) }
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use std::hash::{BuildHasherDefault, Hasher};
|
||||
use std::ops::BitXor;
|
||||
|
||||
/// Type alias for a hashmap using the `fx` hash algorithm.
|
||||
pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
pub(super) type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
|
||||
/// A speedy hash algorithm for use within rustc. The hashmap in alloc by
|
||||
/// default uses SipHash which isn't quite as speedy as we want. In the compiler
|
||||
@ -23,7 +23,7 @@ pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
|
||||
/// similar or slightly worse than FNV, but the speed of the hash function
|
||||
/// itself is much higher because it works on up to 8 bytes at a time.
|
||||
#[derive(Default)]
|
||||
pub struct FxHasher {
|
||||
pub(super) struct FxHasher {
|
||||
hash: usize,
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ macro_rules! rpc_encode_decode {
|
||||
mod tag {
|
||||
#[repr(u8)] enum Tag { $($variant),* }
|
||||
|
||||
$(pub const $variant: u8 = Tag::$variant as u8;)*
|
||||
$(pub(crate) const $variant: u8 = Tag::$variant as u8;)*
|
||||
}
|
||||
|
||||
match self {
|
||||
@ -89,7 +89,7 @@ macro_rules! rpc_encode_decode {
|
||||
mod tag {
|
||||
#[repr(u8)] enum Tag { $($variant),* }
|
||||
|
||||
$(pub const $variant: u8 = Tag::$variant as u8;)*
|
||||
$(pub(crate) const $variant: u8 = Tag::$variant as u8;)*
|
||||
}
|
||||
|
||||
match u8::decode(r, s) {
|
||||
|
@ -44,7 +44,7 @@ macro_rules! define_reify_functions {
|
||||
fn $name:ident $(<$($param:ident),*>)?
|
||||
for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty;
|
||||
)+) => {
|
||||
$(pub const fn $name<
|
||||
$(pub(super) const fn $name<
|
||||
$($($param,)*)?
|
||||
F: Fn($($arg_ty),*) -> $ret_ty + Copy
|
||||
>(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty {
|
||||
|
@ -32,6 +32,7 @@
|
||||
#![allow(internal_features)]
|
||||
#![deny(ffi_unwind_calls)]
|
||||
#![warn(rustdoc::unescaped_backticks)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
#[unstable(feature = "proc_macro_internals", issue = "27812")]
|
||||
#[doc(hidden)]
|
||||
|
@ -44,7 +44,7 @@ impl TestOpts {
|
||||
}
|
||||
|
||||
/// Result of parsing the options.
|
||||
pub type OptRes = Result<TestOpts, String>;
|
||||
pub(crate) type OptRes = Result<TestOpts, String>;
|
||||
/// Result of parsing the option part.
|
||||
type OptPartRes<T> = Result<T, String>;
|
||||
|
||||
|
@ -20,7 +20,7 @@ use super::types::{NamePadding, TestDesc, TestDescAndFn};
|
||||
use super::{filter_tests, run_tests, term};
|
||||
|
||||
/// Generic wrapper over stdout.
|
||||
pub enum OutputLocation<T> {
|
||||
pub(crate) enum OutputLocation<T> {
|
||||
Pretty(Box<term::StdoutTerminal>),
|
||||
Raw(T),
|
||||
}
|
||||
@ -41,7 +41,7 @@ impl<T: Write> Write for OutputLocation<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConsoleTestDiscoveryState {
|
||||
pub(crate) struct ConsoleTestDiscoveryState {
|
||||
pub log_out: Option<File>,
|
||||
pub tests: usize,
|
||||
pub benchmarks: usize,
|
||||
@ -49,7 +49,7 @@ pub struct ConsoleTestDiscoveryState {
|
||||
}
|
||||
|
||||
impl ConsoleTestDiscoveryState {
|
||||
pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestDiscoveryState> {
|
||||
pub(crate) fn new(opts: &TestOpts) -> io::Result<ConsoleTestDiscoveryState> {
|
||||
let log_out = match opts.logfile {
|
||||
Some(ref path) => Some(File::create(path)?),
|
||||
None => None,
|
||||
@ -58,7 +58,7 @@ impl ConsoleTestDiscoveryState {
|
||||
Ok(ConsoleTestDiscoveryState { log_out, tests: 0, benchmarks: 0, ignored: 0 })
|
||||
}
|
||||
|
||||
pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()>
|
||||
pub(crate) fn write_log<F, S>(&mut self, msg: F) -> io::Result<()>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
F: FnOnce() -> S,
|
||||
@ -74,7 +74,7 @@ impl ConsoleTestDiscoveryState {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConsoleTestState {
|
||||
pub(crate) struct ConsoleTestState {
|
||||
pub log_out: Option<File>,
|
||||
pub total: usize,
|
||||
pub passed: usize,
|
||||
@ -92,7 +92,7 @@ pub struct ConsoleTestState {
|
||||
}
|
||||
|
||||
impl ConsoleTestState {
|
||||
pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
|
||||
pub(crate) fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> {
|
||||
let log_out = match opts.logfile {
|
||||
Some(ref path) => Some(File::create(path)?),
|
||||
None => None,
|
||||
@ -116,7 +116,7 @@ impl ConsoleTestState {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()>
|
||||
pub(crate) fn write_log<F, S>(&mut self, msg: F) -> io::Result<()>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
F: FnOnce() -> S,
|
||||
@ -131,7 +131,7 @@ impl ConsoleTestState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_log_result(
|
||||
pub(crate) fn write_log_result(
|
||||
&mut self,
|
||||
test: &TestDesc,
|
||||
result: &TestResult,
|
||||
@ -170,7 +170,7 @@ impl ConsoleTestState {
|
||||
}
|
||||
|
||||
// List the tests to console, and optionally to logfile. Filters are honored.
|
||||
pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
|
||||
pub(crate) fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> {
|
||||
let output = match term::stdout() {
|
||||
None => OutputLocation::Raw(io::stdout().lock()),
|
||||
Some(t) => OutputLocation::Pretty(t),
|
||||
|
@ -13,7 +13,7 @@ pub(crate) struct JsonFormatter<T> {
|
||||
}
|
||||
|
||||
impl<T: Write> JsonFormatter<T> {
|
||||
pub fn new(out: OutputLocation<T>) -> Self {
|
||||
pub(crate) fn new(out: OutputLocation<T>) -> Self {
|
||||
Self { out }
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,13 @@ use crate::test_result::TestResult;
|
||||
use crate::time;
|
||||
use crate::types::{TestDesc, TestType};
|
||||
|
||||
pub struct JunitFormatter<T> {
|
||||
pub(crate) struct JunitFormatter<T> {
|
||||
out: OutputLocation<T>,
|
||||
results: Vec<(TestDesc, TestResult, Duration, Vec<u8>)>,
|
||||
}
|
||||
|
||||
impl<T: Write> JunitFormatter<T> {
|
||||
pub fn new(out: OutputLocation<T>) -> Self {
|
||||
pub(crate) fn new(out: OutputLocation<T>) -> Self {
|
||||
Self { out, results: Vec::new() }
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ pub(crate) struct PrettyFormatter<T> {
|
||||
}
|
||||
|
||||
impl<T: Write> PrettyFormatter<T> {
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
out: OutputLocation<T>,
|
||||
use_color: bool,
|
||||
max_name_len: usize,
|
||||
@ -31,19 +31,19 @@ impl<T: Write> PrettyFormatter<T> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn output_location(&self) -> &OutputLocation<T> {
|
||||
pub(crate) fn output_location(&self) -> &OutputLocation<T> {
|
||||
&self.out
|
||||
}
|
||||
|
||||
pub fn write_ok(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_ok(&mut self) -> io::Result<()> {
|
||||
self.write_short_result("ok", term::color::GREEN)
|
||||
}
|
||||
|
||||
pub fn write_failed(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_failed(&mut self) -> io::Result<()> {
|
||||
self.write_short_result("FAILED", term::color::RED)
|
||||
}
|
||||
|
||||
pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> {
|
||||
pub(crate) fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> {
|
||||
if let Some(message) = message {
|
||||
self.write_short_result(&format!("ignored, {message}"), term::color::YELLOW)
|
||||
} else {
|
||||
@ -51,15 +51,15 @@ impl<T: Write> PrettyFormatter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_time_failed(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_time_failed(&mut self) -> io::Result<()> {
|
||||
self.write_short_result("FAILED (time limit exceeded)", term::color::RED)
|
||||
}
|
||||
|
||||
pub fn write_bench(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_bench(&mut self) -> io::Result<()> {
|
||||
self.write_pretty("bench", term::color::CYAN)
|
||||
}
|
||||
|
||||
pub fn write_short_result(
|
||||
pub(crate) fn write_short_result(
|
||||
&mut self,
|
||||
result: &str,
|
||||
color: term::color::Color,
|
||||
@ -67,7 +67,7 @@ impl<T: Write> PrettyFormatter<T> {
|
||||
self.write_pretty(result, color)
|
||||
}
|
||||
|
||||
pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
|
||||
pub(crate) fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
|
||||
match self.out {
|
||||
OutputLocation::Pretty(ref mut term) => {
|
||||
if self.use_color {
|
||||
@ -86,7 +86,7 @@ impl<T: Write> PrettyFormatter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
|
||||
pub(crate) fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
|
||||
let s = s.as_ref();
|
||||
self.out.write_all(s.as_bytes())?;
|
||||
self.out.flush()
|
||||
@ -154,15 +154,15 @@ impl<T: Write> PrettyFormatter<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
pub(crate) fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
self.write_results(&state.not_failures, "successes")
|
||||
}
|
||||
|
||||
pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
pub(crate) fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
self.write_results(&state.failures, "failures")
|
||||
}
|
||||
|
||||
pub fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
pub(crate) fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
self.write_results(&state.time_failures, "failures (time limit exceeded)")
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub(crate) struct TerseFormatter<T> {
|
||||
}
|
||||
|
||||
impl<T: Write> TerseFormatter<T> {
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
out: OutputLocation<T>,
|
||||
use_color: bool,
|
||||
max_name_len: usize,
|
||||
@ -42,11 +42,11 @@ impl<T: Write> TerseFormatter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_ok(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_ok(&mut self) -> io::Result<()> {
|
||||
self.write_short_result(".", term::color::GREEN)
|
||||
}
|
||||
|
||||
pub fn write_failed(&mut self, name: &str) -> io::Result<()> {
|
||||
pub(crate) fn write_failed(&mut self, name: &str) -> io::Result<()> {
|
||||
// Put failed tests on their own line and include the test name, so that it's faster
|
||||
// to see which test failed without having to wait for them all to run.
|
||||
|
||||
@ -62,15 +62,15 @@ impl<T: Write> TerseFormatter<T> {
|
||||
self.write_plain("\n")
|
||||
}
|
||||
|
||||
pub fn write_ignored(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_ignored(&mut self) -> io::Result<()> {
|
||||
self.write_short_result("i", term::color::YELLOW)
|
||||
}
|
||||
|
||||
pub fn write_bench(&mut self) -> io::Result<()> {
|
||||
pub(crate) fn write_bench(&mut self) -> io::Result<()> {
|
||||
self.write_pretty("bench", term::color::CYAN)
|
||||
}
|
||||
|
||||
pub fn write_short_result(
|
||||
pub(crate) fn write_short_result(
|
||||
&mut self,
|
||||
result: &str,
|
||||
color: term::color::Color,
|
||||
@ -95,7 +95,7 @@ impl<T: Write> TerseFormatter<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
|
||||
pub(crate) fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> {
|
||||
match self.out {
|
||||
OutputLocation::Pretty(ref mut term) => {
|
||||
if self.use_color {
|
||||
@ -114,13 +114,13 @@ impl<T: Write> TerseFormatter<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
|
||||
pub(crate) fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> {
|
||||
let s = s.as_ref();
|
||||
self.out.write_all(s.as_bytes())?;
|
||||
self.out.flush()
|
||||
}
|
||||
|
||||
pub fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
pub(crate) fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
self.write_plain("\nsuccesses:\n")?;
|
||||
let mut successes = Vec::new();
|
||||
let mut stdouts = String::new();
|
||||
@ -146,7 +146,7 @@ impl<T: Write> TerseFormatter<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
pub(crate) fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> {
|
||||
self.write_plain("\nfailures:\n")?;
|
||||
let mut failures = Vec::new();
|
||||
let mut fail_out = String::new();
|
||||
|
@ -4,7 +4,7 @@
|
||||
use std::num::NonZero;
|
||||
use std::{env, thread};
|
||||
|
||||
pub fn get_concurrency() -> usize {
|
||||
pub(crate) fn get_concurrency() -> usize {
|
||||
if let Ok(value) = env::var("RUST_TEST_THREADS") {
|
||||
match value.parse::<NonZero<usize>>().ok() {
|
||||
Some(n) => n.get(),
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Module with common helpers not directly related to tests
|
||||
//! but used in `libtest`.
|
||||
|
||||
pub mod concurrency;
|
||||
pub mod metrics;
|
||||
pub mod shuffle;
|
||||
pub(crate) mod concurrency;
|
||||
pub(crate) mod metrics;
|
||||
pub(crate) mod shuffle;
|
||||
|
@ -4,7 +4,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use crate::cli::TestOpts;
|
||||
use crate::types::{TestDescAndFn, TestId, TestName};
|
||||
|
||||
pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> {
|
||||
pub(crate) fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> {
|
||||
opts.shuffle_seed.or_else(|| {
|
||||
if opts.shuffle {
|
||||
Some(
|
||||
@ -19,7 +19,7 @@ pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) {
|
||||
pub(crate) fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) {
|
||||
let test_names: Vec<&TestName> = tests.iter().map(|test| &test.1.desc.name).collect();
|
||||
let test_names_hash = calculate_hash(&test_names);
|
||||
let mut rng = Rng::new(shuffle_seed, test_names_hash);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#![feature(thread_spawn_hook)]
|
||||
#![allow(internal_features)]
|
||||
#![warn(rustdoc::unescaped_backticks)]
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
pub use cli::TestOpts;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/// Number of times to run a benchmarked function
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum BenchMode {
|
||||
pub(crate) enum BenchMode {
|
||||
Auto,
|
||||
Single,
|
||||
}
|
||||
|
@ -573,13 +573,13 @@ fn test_sum_f64_between_ints_that_sum_to_0() {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn sum_three_items(b: &mut Bencher) {
|
||||
fn sum_three_items(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
[1e20f64, 1.5f64, -1e20f64].sum();
|
||||
})
|
||||
}
|
||||
#[bench]
|
||||
pub fn sum_many_f64(b: &mut Bencher) {
|
||||
fn sum_many_f64(b: &mut Bencher) {
|
||||
let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60];
|
||||
let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>();
|
||||
|
||||
@ -589,4 +589,4 @@ pub fn sum_many_f64(b: &mut Bencher) {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn no_iter(_: &mut Bencher) {}
|
||||
fn no_iter(_: &mut Bencher) {}
|
||||
|
@ -62,7 +62,7 @@ pub(crate) mod color {
|
||||
|
||||
/// A terminal with similar capabilities to an ANSI Terminal
|
||||
/// (foreground/background colors etc).
|
||||
pub trait Terminal: Write {
|
||||
pub(crate) trait Terminal: Write {
|
||||
/// Sets the foreground color to the given color.
|
||||
///
|
||||
/// If the color is a bright color, but the terminal only supports 8 colors,
|
||||
|
@ -12,7 +12,7 @@ use super::types::TestDesc;
|
||||
// Return code for secondary process.
|
||||
// Start somewhere other than 0 so we know the return code means what we think
|
||||
// it means.
|
||||
pub const TR_OK: i32 = 50;
|
||||
pub(crate) const TR_OK: i32 = 50;
|
||||
|
||||
// On Windows we use __fastfail to abort, which is documented to use this
|
||||
// exception code.
|
||||
@ -39,7 +39,7 @@ pub enum TestResult {
|
||||
|
||||
/// Creates a `TestResult` depending on the raw result of test execution
|
||||
/// and associated data.
|
||||
pub fn calc_result<'a>(
|
||||
pub(crate) fn calc_result<'a>(
|
||||
desc: &TestDesc,
|
||||
task_result: Result<(), &'a (dyn Any + 'static + Send)>,
|
||||
time_opts: Option<&time::TestTimeOptions>,
|
||||
@ -93,7 +93,7 @@ pub fn calc_result<'a>(
|
||||
}
|
||||
|
||||
/// Creates a `TestResult` depending on the exit code of test subprocess.
|
||||
pub fn get_result_from_exit_code(
|
||||
pub(crate) fn get_result_from_exit_code(
|
||||
desc: &TestDesc,
|
||||
status: ExitStatus,
|
||||
time_opts: Option<&time::TestTimeOptions>,
|
||||
|
@ -78,7 +78,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn do_not_run_ignored_tests() {
|
||||
fn do_not_run_ignored_tests() {
|
||||
fn f() -> Result<(), String> {
|
||||
panic!();
|
||||
}
|
||||
@ -106,7 +106,7 @@ pub fn do_not_run_ignored_tests() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn ignored_tests_result_in_ignored() {
|
||||
fn ignored_tests_result_in_ignored() {
|
||||
fn f() -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
@ -479,7 +479,7 @@ fn parse_include_ignored_flag() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn filter_for_ignored_option() {
|
||||
fn filter_for_ignored_option() {
|
||||
// When we run ignored tests the test filter should filter out all the
|
||||
// unignored tests and flip the ignore flag on the rest to false
|
||||
|
||||
@ -496,7 +496,7 @@ pub fn filter_for_ignored_option() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn run_include_ignored_option() {
|
||||
fn run_include_ignored_option() {
|
||||
// When we "--include-ignored" tests, the ignore flag should be set to false on
|
||||
// all tests and no test filtered out
|
||||
|
||||
@ -513,7 +513,7 @@ pub fn run_include_ignored_option() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn exclude_should_panic_option() {
|
||||
fn exclude_should_panic_option() {
|
||||
let mut opts = TestOpts::new();
|
||||
opts.run_tests = true;
|
||||
opts.exclude_should_panic = true;
|
||||
@ -544,7 +544,7 @@ pub fn exclude_should_panic_option() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn exact_filter_match() {
|
||||
fn exact_filter_match() {
|
||||
fn tests() -> Vec<TestDescAndFn> {
|
||||
["base", "base::test", "base::test1", "base::test2"]
|
||||
.into_iter()
|
||||
@ -667,7 +667,7 @@ fn sample_tests() -> Vec<TestDescAndFn> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn shuffle_tests() {
|
||||
fn shuffle_tests() {
|
||||
let mut opts = TestOpts::new();
|
||||
opts.shuffle = true;
|
||||
|
||||
@ -686,7 +686,7 @@ pub fn shuffle_tests() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn shuffle_tests_with_seed() {
|
||||
fn shuffle_tests_with_seed() {
|
||||
let mut opts = TestOpts::new();
|
||||
opts.shuffle = true;
|
||||
|
||||
@ -704,7 +704,7 @@ pub fn shuffle_tests_with_seed() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn order_depends_on_more_than_seed() {
|
||||
fn order_depends_on_more_than_seed() {
|
||||
let mut opts = TestOpts::new();
|
||||
opts.shuffle = true;
|
||||
|
||||
@ -732,7 +732,7 @@ pub fn order_depends_on_more_than_seed() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_metricmap_compare() {
|
||||
fn test_metricmap_compare() {
|
||||
let mut m1 = MetricMap::new();
|
||||
let mut m2 = MetricMap::new();
|
||||
m1.insert_metric("in-both-noise", 1000.0, 200.0);
|
||||
@ -755,7 +755,7 @@ pub fn test_metricmap_compare() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_bench_once_no_iter() {
|
||||
fn test_bench_once_no_iter() {
|
||||
fn f(_: &mut Bencher) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
@ -763,7 +763,7 @@ pub fn test_bench_once_no_iter() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_bench_once_iter() {
|
||||
fn test_bench_once_iter() {
|
||||
fn f(b: &mut Bencher) -> Result<(), String> {
|
||||
b.iter(|| {});
|
||||
Ok(())
|
||||
@ -772,7 +772,7 @@ pub fn test_bench_once_iter() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_bench_no_iter() {
|
||||
fn test_bench_no_iter() {
|
||||
fn f(_: &mut Bencher) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
@ -799,7 +799,7 @@ pub fn test_bench_no_iter() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_bench_iter() {
|
||||
fn test_bench_iter() {
|
||||
fn f(b: &mut Bencher) -> Result<(), String> {
|
||||
b.iter(|| {});
|
||||
Ok(())
|
||||
|
@ -11,7 +11,7 @@ use std::{env, fmt};
|
||||
|
||||
use super::types::{TestDesc, TestType};
|
||||
|
||||
pub const TEST_WARN_TIMEOUT_S: u64 = 60;
|
||||
pub(crate) const TEST_WARN_TIMEOUT_S: u64 = 60;
|
||||
|
||||
/// This small module contains constants used by `report-time` option.
|
||||
/// Those constants values will be used if corresponding environment variables are not set.
|
||||
@ -22,42 +22,42 @@ pub const TEST_WARN_TIMEOUT_S: u64 = 60;
|
||||
///
|
||||
/// Example of the expected format is `RUST_TEST_TIME_xxx=100,200`, where 100 means
|
||||
/// warn time, and 200 means critical time.
|
||||
pub mod time_constants {
|
||||
pub(crate) mod time_constants {
|
||||
use std::time::Duration;
|
||||
|
||||
use super::TEST_WARN_TIMEOUT_S;
|
||||
|
||||
/// Environment variable for overriding default threshold for unit-tests.
|
||||
pub const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT";
|
||||
pub(crate) const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT";
|
||||
|
||||
// Unit tests are supposed to be really quick.
|
||||
pub const UNIT_WARN: Duration = Duration::from_millis(50);
|
||||
pub const UNIT_CRITICAL: Duration = Duration::from_millis(100);
|
||||
pub(crate) const UNIT_WARN: Duration = Duration::from_millis(50);
|
||||
pub(crate) const UNIT_CRITICAL: Duration = Duration::from_millis(100);
|
||||
|
||||
/// Environment variable for overriding default threshold for unit-tests.
|
||||
pub const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION";
|
||||
pub(crate) const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION";
|
||||
|
||||
// Integration tests may have a lot of work, so they can take longer to execute.
|
||||
pub const INTEGRATION_WARN: Duration = Duration::from_millis(500);
|
||||
pub const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000);
|
||||
pub(crate) const INTEGRATION_WARN: Duration = Duration::from_millis(500);
|
||||
pub(crate) const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000);
|
||||
|
||||
/// Environment variable for overriding default threshold for unit-tests.
|
||||
pub const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST";
|
||||
pub(crate) const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST";
|
||||
|
||||
// Doctests are similar to integration tests, because they can include a lot of
|
||||
// initialization code.
|
||||
pub const DOCTEST_WARN: Duration = INTEGRATION_WARN;
|
||||
pub const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL;
|
||||
pub(crate) const DOCTEST_WARN: Duration = INTEGRATION_WARN;
|
||||
pub(crate) const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL;
|
||||
|
||||
// Do not suppose anything about unknown tests, base limits on the
|
||||
// `TEST_WARN_TIMEOUT_S` constant.
|
||||
pub const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S);
|
||||
pub const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2);
|
||||
pub(crate) const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S);
|
||||
pub(crate) const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2);
|
||||
}
|
||||
|
||||
/// Returns an `Instance` object denoting when the test should be considered
|
||||
/// timed out.
|
||||
pub fn get_default_test_timeout() -> Instant {
|
||||
pub(crate) fn get_default_test_timeout() -> Instant {
|
||||
Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S)
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ impl fmt::Display for TestExecTime {
|
||||
|
||||
/// The measured execution time of the whole test suite.
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub struct TestSuiteExecTime(pub Duration);
|
||||
pub(crate) struct TestSuiteExecTime(pub Duration);
|
||||
|
||||
impl fmt::Display for TestSuiteExecTime {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -12,6 +12,8 @@ use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use build_helper::ci::CiEnv;
|
||||
|
||||
use crate::Kind;
|
||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::core::config::TargetSelection;
|
||||
@ -112,16 +114,60 @@ impl Step for Gcc {
|
||||
return true;
|
||||
}
|
||||
|
||||
command(root.join("contrib/download_prerequisites")).current_dir(&root).run(builder);
|
||||
command(root.join("configure"))
|
||||
// GCC creates files (e.g. symlinks to the downloaded dependencies)
|
||||
// in the source directory, which does not work with our CI setup, where we mount
|
||||
// source directories as read-only on Linux.
|
||||
// Therefore, as a part of the build in CI, we first copy the whole source directory
|
||||
// to the build directory, and perform the build from there.
|
||||
let src_dir = if CiEnv::is_ci() {
|
||||
let src_dir = builder.gcc_out(target).join("src");
|
||||
if src_dir.exists() {
|
||||
builder.remove_dir(&src_dir);
|
||||
}
|
||||
builder.create_dir(&src_dir);
|
||||
builder.cp_link_r(&root, &src_dir);
|
||||
src_dir
|
||||
} else {
|
||||
root
|
||||
};
|
||||
|
||||
command(src_dir.join("contrib/download_prerequisites")).current_dir(&src_dir).run(builder);
|
||||
let mut configure_cmd = command(src_dir.join("configure"));
|
||||
configure_cmd
|
||||
.current_dir(&out_dir)
|
||||
// On CI, we compile GCC with Clang.
|
||||
// The -Wno-everything flag is needed to make GCC compile with Clang 19.
|
||||
// `-g -O2` are the default flags that are otherwise used by Make.
|
||||
// FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml.
|
||||
.env("CXXFLAGS", "-Wno-everything -g -O2")
|
||||
.env("CFLAGS", "-Wno-everything -g -O2")
|
||||
.arg("--enable-host-shared")
|
||||
.arg("--enable-languages=jit")
|
||||
.arg("--enable-checking=release")
|
||||
.arg("--disable-bootstrap")
|
||||
.arg("--disable-multilib")
|
||||
.arg(format!("--prefix={}", install_dir.display()))
|
||||
.run(builder);
|
||||
.arg(format!("--prefix={}", install_dir.display()));
|
||||
let cc = builder.build.cc(target).display().to_string();
|
||||
let cc = builder
|
||||
.build
|
||||
.config
|
||||
.ccache
|
||||
.as_ref()
|
||||
.map_or_else(|| cc.clone(), |ccache| format!("{ccache} {cc}"));
|
||||
configure_cmd.env("CC", cc);
|
||||
|
||||
if let Ok(ref cxx) = builder.build.cxx(target) {
|
||||
let cxx = cxx.display().to_string();
|
||||
let cxx = builder
|
||||
.build
|
||||
.config
|
||||
.ccache
|
||||
.as_ref()
|
||||
.map_or_else(|| cxx.clone(), |ccache| format!("{ccache} {cxx}"));
|
||||
configure_cmd.env("CXX", cxx);
|
||||
}
|
||||
configure_cmd.run(builder);
|
||||
|
||||
command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs())).run(builder);
|
||||
command("make").current_dir(&out_dir).arg("install").run(builder);
|
||||
|
||||
|
@ -34,6 +34,7 @@ RUN yum upgrade -y && \
|
||||
python3 \
|
||||
unzip \
|
||||
wget \
|
||||
flex \
|
||||
xz \
|
||||
zlib-devel.i686 \
|
||||
zlib-devel.x86_64 \
|
||||
|
@ -25,5 +25,11 @@ cd zstd-$ZSTD
|
||||
CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1
|
||||
hide_output make install
|
||||
|
||||
# It doesn't seem to be possible to move destination directory
|
||||
# of the `make install` above. We thus copy the built artifacts
|
||||
# manually to our custom rustroot, so that it can be found through
|
||||
# LD_LIBRARY_PATH.
|
||||
cp /usr/local/lib/libzstd* /rustroot/lib64
|
||||
|
||||
cd ..
|
||||
rm -rf zstd-$ZSTD
|
||||
|
@ -52,6 +52,8 @@ runners:
|
||||
free_disk: true
|
||||
os: ubuntu-22.04-arm
|
||||
|
||||
- &job-aarch64-linux-8c
|
||||
os: ubuntu-22.04-arm64-8core-32gb
|
||||
envs:
|
||||
env-x86_64-apple-tests: &env-x86_64-apple-tests
|
||||
SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
|
||||
@ -144,7 +146,7 @@ auto:
|
||||
- name: dist-aarch64-linux
|
||||
env:
|
||||
CODEGEN_BACKENDS: llvm,cranelift
|
||||
<<: *job-aarch64-linux
|
||||
<<: *job-aarch64-linux-8c
|
||||
|
||||
- name: dist-android
|
||||
<<: *job-linux-4c
|
||||
|
142
src/ci/scripts/free-disk-space.sh
Executable file
142
src/ci/scripts/free-disk-space.sh
Executable file
@ -0,0 +1,142 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Free disk space on Linux GitHub action runners
|
||||
# Script inspired by https://github.com/jlumbroso/free-disk-space
|
||||
|
||||
# print a line of the specified character
|
||||
printSeparationLine() {
|
||||
for ((i = 0; i < 80; i++)); do
|
||||
printf "%s" "$1"
|
||||
done
|
||||
printf "\n"
|
||||
}
|
||||
|
||||
# compute available space
|
||||
# REF: https://unix.stackexchange.com/a/42049/60849
|
||||
# REF: https://stackoverflow.com/a/450821/408734
|
||||
getAvailableSpace() { echo $(df -a | awk 'NR > 1 {avail+=$4} END {print avail}'); }
|
||||
|
||||
# make Kb human readable (assume the input is Kb)
|
||||
# REF: https://unix.stackexchange.com/a/44087/60849
|
||||
formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); }
|
||||
|
||||
# macro to output saved space
|
||||
printSavedSpace() {
|
||||
# Disk space before the operation
|
||||
local before=${1}
|
||||
local title=${2:-}
|
||||
|
||||
local after
|
||||
after=$(getAvailableSpace)
|
||||
local saved=$((after - before))
|
||||
|
||||
echo ""
|
||||
printSeparationLine "*"
|
||||
if [ -n "${title}" ]; then
|
||||
echo "=> ${title}: Saved $(formatByteCount "$saved")"
|
||||
else
|
||||
echo "=> Saved $(formatByteCount "$saved")"
|
||||
fi
|
||||
printSeparationLine "*"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# macro to print output of df with caption
|
||||
printDF() {
|
||||
local caption=${1}
|
||||
|
||||
printSeparationLine "="
|
||||
echo "${caption}"
|
||||
echo ""
|
||||
echo "$ df -h"
|
||||
echo ""
|
||||
df -h
|
||||
printSeparationLine "="
|
||||
}
|
||||
|
||||
removeDir() {
|
||||
dir=${1}
|
||||
|
||||
local before
|
||||
before=$(getAvailableSpace)
|
||||
|
||||
sudo rm -rf "$dir" || true
|
||||
|
||||
printSavedSpace "$before" "$dir"
|
||||
}
|
||||
|
||||
execAndMeasureSpaceChange() {
|
||||
local operation=${1} # Function to execute
|
||||
local title=${2}
|
||||
|
||||
local before
|
||||
before=$(getAvailableSpace)
|
||||
$operation
|
||||
|
||||
printSavedSpace "$before" "$title"
|
||||
}
|
||||
|
||||
# Remove large packages
|
||||
# REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh
|
||||
cleanPackages() {
|
||||
sudo apt-get -qq remove -y --fix-missing \
|
||||
'^aspnetcore-.*' \
|
||||
'^dotnet-.*' \
|
||||
'^llvm-.*' \
|
||||
'php.*' \
|
||||
'^mongodb-.*' \
|
||||
'^mysql-.*' \
|
||||
'azure-cli' \
|
||||
'google-chrome-stable' \
|
||||
'firefox' \
|
||||
'powershell' \
|
||||
'mono-devel' \
|
||||
'libgl1-mesa-dri' \
|
||||
'google-cloud-sdk' \
|
||||
'google-cloud-cli'
|
||||
|
||||
sudo apt-get autoremove -y || echo "::warning::The command [sudo apt-get autoremove -y] failed"
|
||||
sudo apt-get clean || echo "::warning::The command [sudo apt-get clean] failed failed"
|
||||
}
|
||||
|
||||
# Remove Docker images
|
||||
cleanDocker() {
|
||||
echo "Removing the following docker images:"
|
||||
sudo docker image ls
|
||||
echo "Removing docker images..."
|
||||
sudo docker image prune --all --force || true
|
||||
}
|
||||
|
||||
# Remove Swap storage
|
||||
cleanSwap() {
|
||||
sudo swapoff -a || true
|
||||
sudo rm -rf /mnt/swapfile || true
|
||||
free -h
|
||||
}
|
||||
|
||||
# Display initial disk space stats
|
||||
|
||||
AVAILABLE_INITIAL=$(getAvailableSpace)
|
||||
|
||||
printDF "BEFORE CLEAN-UP:"
|
||||
echo ""
|
||||
|
||||
removeDir /usr/local/lib/android
|
||||
removeDir /usr/share/dotnet
|
||||
|
||||
# Haskell runtime
|
||||
removeDir /opt/ghc
|
||||
removeDir /usr/local/.ghcup
|
||||
|
||||
execAndMeasureSpaceChange cleanPackages "Large misc. packages"
|
||||
execAndMeasureSpaceChange cleanDocker "Docker images"
|
||||
execAndMeasureSpaceChange cleanSwap "Swap storage"
|
||||
|
||||
# Output saved space statistic
|
||||
echo ""
|
||||
printDF "AFTER CLEAN-UP:"
|
||||
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
printSavedSpace "$AVAILABLE_INITIAL" "Total saved"
|
199
tests/assembly/wasm32-naked-fn.rs
Normal file
199
tests/assembly/wasm32-naked-fn.rs
Normal file
@ -0,0 +1,199 @@
|
||||
// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed
|
||||
// see https://github.com/rust-lang/rust/issues/115666
|
||||
//@ revisions: wasm64-unknown wasm32-wasip1
|
||||
//@ add-core-stubs
|
||||
//@ assembly-output: emit-asm
|
||||
//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown
|
||||
//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1
|
||||
//@ [wasm64-unknown] needs-llvm-components: webassembly
|
||||
//@ [wasm32-wasip1] needs-llvm-components: webassembly
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)]
|
||||
#![no_core]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
// CHECK: .section .text.nop,"",@
|
||||
// CHECK: .globl nop
|
||||
// CHECK-LABEL: nop:
|
||||
// CHECK: .functype nop () -> ()
|
||||
// CHECK-NOT: .size
|
||||
// CHECK: end_function
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn nop() {
|
||||
naked_asm!("nop")
|
||||
}
|
||||
|
||||
// CHECK: .section .text.weak_aligned_nop,"",@
|
||||
// CHECK: .weak weak_aligned_nop
|
||||
// CHECK-LABEL: nop:
|
||||
// CHECK: .functype weak_aligned_nop () -> ()
|
||||
// CHECK-NOT: .size
|
||||
// CHECK: end_function
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
#[linkage = "weak"]
|
||||
// wasm functions cannot be aligned, so this has no effect
|
||||
#[repr(align(32))]
|
||||
unsafe extern "C" fn weak_aligned_nop() {
|
||||
naked_asm!("nop")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i8_i8:
|
||||
// CHECK-NEXT: .functype fn_i8_i8 (i32) -> (i32)
|
||||
//
|
||||
// CHECK-NEXT: local.get 0
|
||||
// CHECK-NEXT: local.get 0
|
||||
// CHECK-NEXT: i32.mul
|
||||
//
|
||||
// CHECK-NEXT: end_function
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i8_i8(num: i8) -> i8 {
|
||||
naked_asm!("local.get 0", "local.get 0", "i32.mul")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i8_i8_i8:
|
||||
// CHECK: .functype fn_i8_i8_i8 (i32, i32) -> (i32)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i8_i8_i8(a: i8, b: i8) -> i8 {
|
||||
naked_asm!("local.get 1", "local.get 0", "i32.mul")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_unit_i8:
|
||||
// CHECK: .functype fn_unit_i8 () -> (i32)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_unit_i8() -> i8 {
|
||||
naked_asm!("i32.const 42")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i8_unit:
|
||||
// CHECK: .functype fn_i8_unit (i32) -> ()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i8_unit(_: i8) {
|
||||
naked_asm!("nop")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i32_i32:
|
||||
// CHECK: .functype fn_i32_i32 (i32) -> (i32)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i32_i32(num: i32) -> i32 {
|
||||
naked_asm!("local.get 0", "local.get 0", "i32.mul")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i64_i64:
|
||||
// CHECK: .functype fn_i64_i64 (i64) -> (i64)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 {
|
||||
naked_asm!("local.get 0", "local.get 0", "i64.mul")
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_i128_i128:
|
||||
// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
|
||||
// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> ()
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 {
|
||||
naked_asm!(
|
||||
"local.get 0",
|
||||
"local.get 2",
|
||||
"i64.store 8",
|
||||
"local.get 0",
|
||||
"local.get 1",
|
||||
"i64.store 0",
|
||||
)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_f128_f128:
|
||||
// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
|
||||
// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> ()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_f128_f128(num: f128) -> f128 {
|
||||
naked_asm!(
|
||||
"local.get 0",
|
||||
"local.get 2",
|
||||
"i64.store 8",
|
||||
"local.get 0",
|
||||
"local.get 1",
|
||||
"i64.store 0",
|
||||
)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct Compound {
|
||||
a: u16,
|
||||
b: i64,
|
||||
}
|
||||
|
||||
// CHECK-LABEL: fn_compound_compound:
|
||||
// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> ()
|
||||
// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> ()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound {
|
||||
// this is the wasm32-wasip1 assembly
|
||||
naked_asm!(
|
||||
"local.get 0",
|
||||
"local.get 1",
|
||||
"i64.load 8",
|
||||
"i64.store 8",
|
||||
"local.get 0",
|
||||
"local.get 1",
|
||||
"i32.load16_u 0",
|
||||
"i32.store16 0",
|
||||
)
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct WrapperI32(i32);
|
||||
|
||||
// CHECK-LABEL: fn_wrapperi32_wrapperi32:
|
||||
// CHECK: .functype fn_wrapperi32_wrapperi32 (i32) -> (i32)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_wrapperi32_wrapperi32(_: WrapperI32) -> WrapperI32 {
|
||||
naked_asm!("local.get 0")
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct WrapperI64(i64);
|
||||
|
||||
// CHECK-LABEL: fn_wrapperi64_wrapperi64:
|
||||
// CHECK: .functype fn_wrapperi64_wrapperi64 (i64) -> (i64)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_wrapperi64_wrapperi64(_: WrapperI64) -> WrapperI64 {
|
||||
naked_asm!("local.get 0")
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct WrapperF32(f32);
|
||||
|
||||
// CHECK-LABEL: fn_wrapperf32_wrapperf32:
|
||||
// CHECK: .functype fn_wrapperf32_wrapperf32 (f32) -> (f32)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_wrapperf32_wrapperf32(_: WrapperF32) -> WrapperF32 {
|
||||
naked_asm!("local.get 0")
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct WrapperF64(f64);
|
||||
|
||||
// CHECK-LABEL: fn_wrapperf64_wrapperf64:
|
||||
// CHECK: .functype fn_wrapperf64_wrapperf64 (f64) -> (f64)
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
unsafe extern "C" fn fn_wrapperf64_wrapperf64(_: WrapperF64) -> WrapperF64 {
|
||||
naked_asm!("local.get 0")
|
||||
}
|
Loading…
Reference in New Issue
Block a user