Auto merge of #117071 - matthiaskrgr:rollup-1tcxdgj, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #105666 (rustdoc: align stability badge to baseline instead of bottom)
 - #117042 (coverage: Emit the filenames section before encoding per-function mappings)
 - #117044 (Miri subtree update)
 - #117049 (add a `csky-unknown-linux-gnuabiv2hf` target )
 - #117051 (fix broken link: update incremental compilation url)
 - #117069 (x.ps1: remove the check for Python from Windows Store)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-10-23 07:32:55 +00:00
commit 6bb4ad6dfb
21 changed files with 204 additions and 126 deletions

View File

@ -3601,6 +3601,7 @@ version = "0.0.0"
dependencies = [
"bitflags 1.3.2",
"cstr",
"itertools",
"libc",
"measureme",
"object",

View File

@ -9,6 +9,7 @@ test = false
[dependencies]
bitflags = "1.0"
cstr = "0.2"
itertools = "0.10.5"
libc = "0.2"
measureme = "10.0.0"
object = { version = "0.32.0", default-features = false, features = [

View File

@ -1,16 +1,18 @@
use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::coverage::{
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, Op,
};
use rustc_middle::ty::Instance;
use rustc_span::Symbol;
/// Holds all of the coverage mapping data associated with a function instance,
/// collected during traversal of `Coverage` statements in the function's MIR.
#[derive(Debug)]
pub struct FunctionCoverage<'tcx> {
pub struct FunctionCoverageCollector<'tcx> {
/// Coverage info that was attached to this function by the instrumentor.
function_coverage_info: &'tcx FunctionCoverageInfo,
is_used: bool,
@ -26,7 +28,7 @@ pub struct FunctionCoverage<'tcx> {
expressions_seen: BitSet<ExpressionId>,
}
impl<'tcx> FunctionCoverage<'tcx> {
impl<'tcx> FunctionCoverageCollector<'tcx> {
/// Creates a new set of coverage data for a used (called) function.
pub fn new(
instance: Instance<'tcx>,
@ -76,11 +78,6 @@ impl<'tcx> FunctionCoverage<'tcx> {
}
}
/// Returns true for a used (called) function, and false for an unused function.
pub fn is_used(&self) -> bool {
self.is_used
}
/// Marks a counter ID as having been seen in a counter-increment statement.
#[instrument(level = "debug", skip(self))]
pub(crate) fn mark_counter_id_seen(&mut self, id: CounterId) {
@ -165,64 +162,71 @@ impl<'tcx> FunctionCoverage<'tcx> {
ZeroExpressions(zero_expressions)
}
pub(crate) fn into_finished(self) -> FunctionCoverage<'tcx> {
let zero_expressions = self.identify_zero_expressions();
let FunctionCoverageCollector { function_coverage_info, is_used, counters_seen, .. } = self;
FunctionCoverage { function_coverage_info, is_used, counters_seen, zero_expressions }
}
}
pub(crate) struct FunctionCoverage<'tcx> {
function_coverage_info: &'tcx FunctionCoverageInfo,
is_used: bool,
counters_seen: BitSet<CounterId>,
zero_expressions: ZeroExpressions,
}
impl<'tcx> FunctionCoverage<'tcx> {
/// Returns true for a used (called) function, and false for an unused function.
pub(crate) fn is_used(&self) -> bool {
self.is_used
}
/// Return the source hash, generated from the HIR node structure, and used to indicate whether
/// or not the source code structure changed between different compilations.
pub fn source_hash(&self) -> u64 {
if self.is_used { self.function_coverage_info.function_source_hash } else { 0 }
}
/// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their
/// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create
/// `CounterMappingRegion`s.
pub fn get_expressions_and_counter_regions(
&self,
) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &CodeRegion)>) {
let zero_expressions = self.identify_zero_expressions();
let counter_expressions = self.counter_expressions(&zero_expressions);
// Expression IDs are indices into `self.expressions`, and on the LLVM
// side they will be treated as indices into `counter_expressions`, so
// the two vectors should correspond 1:1.
assert_eq!(self.function_coverage_info.expressions.len(), counter_expressions.len());
let counter_regions = self.counter_regions(zero_expressions);
(counter_expressions, counter_regions)
/// Returns an iterator over all filenames used by this function's mappings.
pub(crate) fn all_file_names(&self) -> impl Iterator<Item = Symbol> + Captures<'_> {
self.function_coverage_info.mappings.iter().map(|mapping| mapping.code_region.file_name)
}
/// Convert this function's coverage expression data into a form that can be
/// passed through FFI to LLVM.
fn counter_expressions(&self, zero_expressions: &ZeroExpressions) -> Vec<CounterExpression> {
pub(crate) fn counter_expressions(
&self,
) -> impl Iterator<Item = CounterExpression> + ExactSizeIterator + Captures<'_> {
// We know that LLVM will optimize out any unused expressions before
// producing the final coverage map, so there's no need to do the same
// thing on the Rust side unless we're confident we can do much better.
// (See `CounterExpressionsMinimizer` in `CoverageMappingWriter.cpp`.)
let counter_from_operand = |operand: CovTerm| match operand {
CovTerm::Expression(id) if zero_expressions.contains(id) => Counter::ZERO,
CovTerm::Expression(id) if self.zero_expressions.contains(id) => Counter::ZERO,
_ => Counter::from_term(operand),
};
self.function_coverage_info
.expressions
.iter()
.map(|&Expression { lhs, op, rhs }| CounterExpression {
self.function_coverage_info.expressions.iter().map(move |&Expression { lhs, op, rhs }| {
CounterExpression {
lhs: counter_from_operand(lhs),
kind: match op {
Op::Add => ExprKind::Add,
Op::Subtract => ExprKind::Subtract,
},
rhs: counter_from_operand(rhs),
})
.collect::<Vec<_>>()
}
})
}
/// Converts this function's coverage mappings into an intermediate form
/// that will be used by `mapgen` when preparing for FFI.
fn counter_regions(
pub(crate) fn counter_regions(
&self,
zero_expressions: ZeroExpressions,
) -> impl Iterator<Item = (Counter, &CodeRegion)> {
) -> impl Iterator<Item = (Counter, &CodeRegion)> + ExactSizeIterator {
// Historically, mappings were stored directly in counter/expression
// statements in MIR, and MIR optimizations would sometimes remove them.
// That's mostly no longer true, so now we detect cases where that would
@ -230,7 +234,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
let counter_for_term = move |term: CovTerm| {
let force_to_zero = match term {
CovTerm::Counter(id) => !self.counters_seen.contains(id),
CovTerm::Expression(id) => zero_expressions.contains(id),
CovTerm::Expression(id) => self.zero_expressions.contains(id),
CovTerm::Zero => false,
};
if force_to_zero { Counter::ZERO } else { Counter::from_term(term) }

View File

@ -1,11 +1,12 @@
use crate::common::CodegenCx;
use crate::coverageinfo;
use crate::coverageinfo::ffi::CounterMappingRegion;
use crate::coverageinfo::map_data::FunctionCoverage;
use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector};
use crate::llvm;
use itertools::Itertools as _;
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
@ -57,11 +58,32 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
return;
}
let mut global_file_table = GlobalFileTable::new(tcx);
let function_coverage_entries = function_coverage_map
.into_iter()
.map(|(instance, function_coverage)| (instance, function_coverage.into_finished()))
.collect::<Vec<_>>();
let all_file_names =
function_coverage_entries.iter().flat_map(|(_, fn_cov)| fn_cov.all_file_names());
let global_file_table = GlobalFileTable::new(all_file_names);
// Encode all filenames referenced by coverage mappings in this CGU.
let filenames_buffer = global_file_table.make_filenames_buffer(tcx);
let filenames_size = filenames_buffer.len();
let filenames_val = cx.const_bytes(&filenames_buffer);
let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer);
// Generate the coverage map header, which contains the filenames used by
// this CGU's coverage mappings, and store it in a well-known global.
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
let mut unused_function_names = Vec::new();
let covfun_section_name = coverageinfo::covfun_section_name(cx);
// Encode coverage mappings and generate function records
let mut function_data = Vec::new();
for (instance, function_coverage) in function_coverage_map {
for (instance, function_coverage) in function_coverage_entries {
debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance);
let mangled_function_name = tcx.symbol_name(instance).name;
@ -69,7 +91,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
let is_used = function_coverage.is_used();
let coverage_mapping_buffer =
encode_mappings_for_function(&mut global_file_table, &function_coverage);
encode_mappings_for_function(&global_file_table, &function_coverage);
if coverage_mapping_buffer.is_empty() {
if function_coverage.is_used() {
@ -83,23 +105,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
}
}
function_data.push((mangled_function_name, source_hash, is_used, coverage_mapping_buffer));
}
// Encode all filenames referenced by counters/expressions in this module
let filenames_buffer = global_file_table.into_filenames_buffer();
let filenames_size = filenames_buffer.len();
let filenames_val = cx.const_bytes(&filenames_buffer);
let filenames_ref = coverageinfo::hash_bytes(&filenames_buffer);
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
let cov_data_val = generate_coverage_map(cx, version, filenames_size, filenames_val);
let mut unused_function_names = Vec::new();
let covfun_section_name = coverageinfo::covfun_section_name(cx);
for (mangled_function_name, source_hash, is_used, coverage_mapping_buffer) in function_data {
if !is_used {
unused_function_names.push(mangled_function_name);
}
@ -133,92 +138,125 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
llvm::set_linkage(array, llvm::Linkage::InternalLinkage);
llvm::set_initializer(array, initializer);
}
// Save the coverage data value to LLVM IR
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
}
/// Maps "global" (per-CGU) file ID numbers to their underlying filenames.
struct GlobalFileTable {
global_file_table: FxIndexSet<Symbol>,
/// This "raw" table doesn't include the working dir, so a filename's
/// global ID is its index in this set **plus one**.
raw_file_table: FxIndexSet<Symbol>,
}
impl GlobalFileTable {
fn new(tcx: TyCtxt<'_>) -> Self {
let mut global_file_table = FxIndexSet::default();
fn new(all_file_names: impl IntoIterator<Item = Symbol>) -> Self {
// Collect all of the filenames into a set. Filenames usually come in
// contiguous runs, so we can dedup adjacent ones to save work.
let mut raw_file_table = all_file_names.into_iter().dedup().collect::<FxIndexSet<Symbol>>();
// Sort the file table by its actual string values, not the arbitrary
// ordering of its symbols.
raw_file_table.sort_unstable_by(|a, b| a.as_str().cmp(b.as_str()));
Self { raw_file_table }
}
fn global_file_id_for_file_name(&self, file_name: Symbol) -> u32 {
let raw_id = self.raw_file_table.get_index_of(&file_name).unwrap_or_else(|| {
bug!("file name not found in prepared global file table: {file_name}");
});
// The raw file table doesn't include an entry for the working dir
// (which has ID 0), so add 1 to get the correct ID.
(raw_id + 1) as u32
}
fn make_filenames_buffer(&self, tcx: TyCtxt<'_>) -> Vec<u8> {
// LLVM Coverage Mapping Format version 6 (zero-based encoded as 5)
// requires setting the first filename to the compilation directory.
// Since rustc generates coverage maps with relative paths, the
// compilation directory can be combined with the relative paths
// to get absolute paths, if needed.
use rustc_session::RemapFileNameExt;
let working_dir =
Symbol::intern(&tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy());
global_file_table.insert(working_dir);
Self { global_file_table }
}
fn global_file_id_for_file_name(&mut self, file_name: Symbol) -> u32 {
let (global_file_id, _) = self.global_file_table.insert_full(file_name);
global_file_id as u32
}
fn into_filenames_buffer(self) -> Vec<u8> {
// This method takes `self` so that the caller can't accidentally
// modify the original file table after encoding it into a buffer.
let working_dir: &str = &tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy();
llvm::build_byte_buffer(|buffer| {
coverageinfo::write_filenames_section_to_buffer(
self.global_file_table.iter().map(Symbol::as_str),
// Insert the working dir at index 0, before the other filenames.
std::iter::once(working_dir).chain(self.raw_file_table.iter().map(Symbol::as_str)),
buffer,
);
})
}
}
rustc_index::newtype_index! {
// Tell the newtype macro to not generate `Encode`/`Decode` impls.
#[custom_encodable]
struct LocalFileId {}
}
/// Holds a mapping from "local" (per-function) file IDs to "global" (per-CGU)
/// file IDs.
#[derive(Default)]
struct VirtualFileMapping {
local_to_global: IndexVec<LocalFileId, u32>,
global_to_local: FxIndexMap<u32, LocalFileId>,
}
impl VirtualFileMapping {
fn local_id_for_global(&mut self, global_file_id: u32) -> LocalFileId {
*self
.global_to_local
.entry(global_file_id)
.or_insert_with(|| self.local_to_global.push(global_file_id))
}
fn into_vec(self) -> Vec<u32> {
self.local_to_global.raw
}
}
/// Using the expressions and counter regions collected for a single function,
/// generate the variable-sized payload of its corresponding `__llvm_covfun`
/// entry. The payload is returned as a vector of bytes.
///
/// Newly-encountered filenames will be added to the global file table.
fn encode_mappings_for_function(
global_file_table: &mut GlobalFileTable,
global_file_table: &GlobalFileTable,
function_coverage: &FunctionCoverage<'_>,
) -> Vec<u8> {
let (expressions, counter_regions) = function_coverage.get_expressions_and_counter_regions();
let mut counter_regions = counter_regions.collect::<Vec<_>>();
let counter_regions = function_coverage.counter_regions();
if counter_regions.is_empty() {
return Vec::new();
}
let mut virtual_file_mapping = IndexVec::<u32, u32>::new();
let expressions = function_coverage.counter_expressions().collect::<Vec<_>>();
let mut virtual_file_mapping = VirtualFileMapping::default();
let mut mapping_regions = Vec::with_capacity(counter_regions.len());
// Sort and group the list of (counter, region) mapping pairs by filename.
// (Preserve any further ordering imposed by `FunctionCoverage`.)
// Group mappings into runs with the same filename, preserving the order
// yielded by `FunctionCoverage`.
// Prepare file IDs for each filename, and prepare the mapping data so that
// we can pass it through FFI to LLVM.
counter_regions.sort_by_key(|(_counter, region)| region.file_name);
for counter_regions_for_file in
counter_regions.group_by(|(_, a), (_, b)| a.file_name == b.file_name)
for (file_name, counter_regions_for_file) in
&counter_regions.group_by(|(_counter, region)| region.file_name)
{
// Look up (or allocate) the global file ID for this filename.
let file_name = counter_regions_for_file[0].1.file_name;
// Look up the global file ID for this filename.
let global_file_id = global_file_table.global_file_id_for_file_name(file_name);
// Associate that global file ID with a local file ID for this function.
let local_file_id: u32 = virtual_file_mapping.push(global_file_id);
debug!(" file id: local {local_file_id} => global {global_file_id} = '{file_name:?}'");
let local_file_id = virtual_file_mapping.local_id_for_global(global_file_id);
debug!(" file id: {local_file_id:?} => global {global_file_id} = '{file_name:?}'");
// For each counter/region pair in this function+file, convert it to a
// form suitable for FFI.
for &(counter, region) in counter_regions_for_file {
for (counter, region) in counter_regions_for_file {
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = *region;
debug!("Adding counter {counter:?} to map for {region:?}");
mapping_regions.push(CounterMappingRegion::code_region(
counter,
local_file_id,
local_file_id.as_u32(),
start_line,
start_col,
end_line,
@ -230,7 +268,7 @@ fn encode_mappings_for_function(
// Encode the function's coverage mappings into a buffer.
llvm::build_byte_buffer(|buffer| {
coverageinfo::write_mapping_to_buffer(
virtual_file_mapping.raw,
virtual_file_mapping.into_vec(),
expressions,
mapping_regions,
buffer,
@ -419,7 +457,7 @@ fn add_unused_function_coverage<'tcx>(
) {
// An unused function's mappings will automatically be rewritten to map to
// zero, because none of its counters/expressions are marked as seen.
let function_coverage = FunctionCoverage::unused(instance, function_coverage_info);
let function_coverage = FunctionCoverageCollector::unused(instance, function_coverage_info);
if let Some(coverage_context) = cx.coverage_context() {
coverage_context.function_coverage_map.borrow_mut().insert(instance, function_coverage);

View File

@ -3,7 +3,7 @@ use crate::llvm;
use crate::builder::Builder;
use crate::common::CodegenCx;
use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion};
use crate::coverageinfo::map_data::FunctionCoverage;
use crate::coverageinfo::map_data::FunctionCoverageCollector;
use libc::c_uint;
use rustc_codegen_ssa::traits::{
@ -29,7 +29,8 @@ const VAR_ALIGN_BYTES: usize = 8;
/// A context object for maintaining all state needed by the coverageinfo module.
pub struct CrateCoverageContext<'ll, 'tcx> {
/// Coverage data for each instrumented function identified by DefId.
pub(crate) function_coverage_map: RefCell<FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>>,
pub(crate) function_coverage_map:
RefCell<FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>,
pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
}
@ -41,7 +42,9 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
}
}
pub fn take_function_coverage_map(&self) -> FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>> {
pub fn take_function_coverage_map(
&self,
) -> FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> {
self.function_coverage_map.replace(FxHashMap::default())
}
}
@ -93,7 +96,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
let mut coverage_map = coverage_context.function_coverage_map.borrow_mut();
let func_coverage = coverage_map
.entry(instance)
.or_insert_with(|| FunctionCoverage::new(instance, function_coverage_info));
.or_insert_with(|| FunctionCoverageCollector::new(instance, function_coverage_info));
let Coverage { kind } = coverage;
match *kind {

View File

@ -8,12 +8,13 @@
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(exact_size_is_empty)]
#![feature(extern_types)]
#![feature(hash_raw_entry)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(slice_group_by)]
#![feature(impl_trait_in_assoc_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]

View File

@ -332,7 +332,7 @@ impl<D: Deps> DepGraphData<D> {
/// - If you need 3+ arguments, use a tuple for the
/// `arg` parameter.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html
#[inline(always)]
pub fn with_task<Ctxt: HasDepContext<Deps = D>, A: Debug, R>(
&self,

View File

@ -12,7 +12,7 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "abiv2".into(),
features: "+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(),
late_link_args_static: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]),
late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a"]),
max_atomic_width: Some(32),
..super::linux_gnu_base::opts()
},

View File

@ -0,0 +1,21 @@
use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};
// This target is for glibc Linux on Csky
pub fn target() -> Target {
Target {
//https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
llvm_target: "csky-unknown-linux-gnuabiv2".into(),
pointer_width: 32,
data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(),
arch: "csky".into(),
options: TargetOptions {
abi: "abiv2hf".into(),
cpu: "ck860fv".into(),
features: "+hard-float,+hard-float-abi,+2e3,+3e7,+7e10,+cache,+dsp1e2,+dspe60,+e1,+e2,+edsp,+elrw,+hard-tp,+high-registers,+hwdiv,+mp,+mp1e2,+nvic,+trust".into(),
late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-l:libatomic.a", "-mhard-float"]),
max_atomic_width: Some(32),
..super::linux_gnu_base::opts()
},
}
}

View File

@ -1344,6 +1344,7 @@ supported_targets! {
("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
("csky-unknown-linux-gnuabiv2", csky_unknown_linux_gnuabiv2),
("csky-unknown-linux-gnuabiv2hf", csky_unknown_linux_gnuabiv2hf),
("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),

View File

@ -33,7 +33,7 @@
- [\*-esp-espidf](platform-support/esp-idf.md)
- [\*-unknown-fuchsia](platform-support/fuchsia.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md)
- [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md)
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
- [loongarch\*-unknown-none\*](platform-support/loongarch-none.md)
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)

View File

@ -259,7 +259,8 @@ target | std | host | notes
`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core`
`bpfeb-unknown-none` | * | | BPF (big endian)
`bpfel-unknown-none` | * | | BPF (little endian)
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian)
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian)
`hexagon-unknown-linux-musl` | ? | |
`i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI]
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI]

View File

@ -4,7 +4,14 @@
This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`.
target | std | host | notes
-------|:---:|:----:|-------
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian)
Reference:
https://c-sky.github.io/
https://gitlab.com/c-sky/
## Target maintainers
@ -13,7 +20,6 @@ https://gitlab.com/c-sky/
## Requirements
## Building the target
### Get a C toolchain
@ -28,13 +34,17 @@ The target can be built by enabling it for a `rustc` build, by placing the follo
```toml
[build]
target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"]
target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2", "csky-unknown-linux-gnuabiv2hf"]
stage = 2
[target.csky-unknown-linux-gnuabiv2]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
[target.csky-unknown-linux-gnuabiv2hf]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
### Build
```sh

View File

@ -1107,6 +1107,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
white-space: pre-wrap;
border-radius: 3px;
display: inline;
vertical-align: baseline;
}
.stab.portability > code {

View File

@ -102,6 +102,7 @@ static TARGETS: &[&str] = &[
"loongarch64-unknown-none-softfloat",
"m68k-unknown-linux-gnu",
"csky-unknown-linux-gnuabiv2",
"csky-unknown-linux-gnuabiv2hf",
"mips-unknown-linux-gnu",
"mips-unknown-linux-musl",
"mips64-unknown-linux-gnuabi64",

View File

@ -1 +1 @@
249624b5043013d18c00f0401ca431c1a6baa8cd
9e3f784eb2c7c847b6c3578b373c0e0bc9233ca3

View File

@ -1,4 +1,4 @@
use std::sync::atomic::{AtomicU64, Ordering};
use std::cell::Cell;
use std::time::{Duration, Instant as StdInstant};
/// When using a virtual clock, this defines how many nanoseconds we pretend are passing for each
@ -59,7 +59,7 @@ enum ClockKind {
},
Virtual {
/// The "current virtual time".
nanoseconds: AtomicU64,
nanoseconds: Cell<u64>,
},
}
@ -82,7 +82,7 @@ impl Clock {
// Time will pass without us doing anything.
}
ClockKind::Virtual { nanoseconds } => {
nanoseconds.fetch_add(NANOSECONDS_PER_BASIC_BLOCK, Ordering::SeqCst);
nanoseconds.update(|x| x + NANOSECONDS_PER_BASIC_BLOCK);
}
}
}
@ -93,7 +93,8 @@ impl Clock {
ClockKind::Host { .. } => std::thread::sleep(duration),
ClockKind::Virtual { nanoseconds } => {
// Just pretend that we have slept for some time.
nanoseconds.fetch_add(duration.as_nanos().try_into().unwrap(), Ordering::SeqCst);
let nanos: u64 = duration.as_nanos().try_into().unwrap();
nanoseconds.update(|x| x + nanos);
}
}
}
@ -110,9 +111,7 @@ impl Clock {
match &self.kind {
ClockKind::Host { .. } => Instant { kind: InstantKind::Host(StdInstant::now()) },
ClockKind::Virtual { nanoseconds } =>
Instant {
kind: InstantKind::Virtual { nanoseconds: nanoseconds.load(Ordering::SeqCst) },
},
Instant { kind: InstantKind::Virtual { nanoseconds: nanoseconds.get() } },
}
}
}

View File

@ -1,4 +1,5 @@
#![feature(rustc_private)]
#![feature(cell_update)]
#![feature(float_gamma)]
#![feature(map_try_insert)]
#![feature(never_type)]

View File

@ -37,7 +37,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_mut();
let tcx = this.tcx;
let flags = if let Some(flags_op) = args.get(0) {
let flags = if let Some(flags_op) = args.first() {
this.read_scalar(flags_op)?.to_u64()?
} else {
throw_ub_format!("expected at least 1 argument")

View File

@ -3,12 +3,12 @@
WINDOWS: $__llvm_profile_runtime_user = comdat any
CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
CHECK: @__llvm_coverage_mapping = private constant
CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
CHECK: @__covrec_{{[A-F0-9]+}}u = linkonce_odr hidden constant
CHECK-SAME: section "[[INSTR_PROF_COVFUN]]"[[COMDAT_IF_SUPPORTED]], align 8
WINDOWS: @__llvm_profile_runtime = external{{.*}}global i32
CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = {{private|internal}} global

5
x.ps1
View File

@ -17,11 +17,6 @@ foreach ($arg in $args) {
function Get-Application($app) {
$cmd = Get-Command $app -ErrorAction SilentlyContinue -CommandType Application | Select-Object -First 1
if ($cmd.source -match '.*AppData\\Local\\Microsoft\\WindowsApps\\.*exe') {
# Windows for some reason puts a `python3.exe` executable in PATH that just opens the windows store.
# Ignore it.
return $false
}
return $cmd
}