Skip to content

Commit fca1481

Browse files
authored
Rollup merge of #133720 - c410-f3r:cfg-match-foo-bar-baz, r=joshtriplett
[cfg_match] Adjust syntax A year has passed since the creation of #115585 and the feature, as expected, is not moving forward. Let's change that. This PR proposes changing the arm's syntax from `cfg(SOME_CONDITION) => { ... }` to `SOME_CODITION => {}`. ```rust match_cfg! { unix => { fn foo() { /* unix specific functionality */ } } target_pointer_width = "32" => { fn foo() { /* non-unix, 32-bit functionality */ } } _ => { fn foo() { /* fallback implementation */ } } } ``` Why? Because after several manual migrations in #116342 it became clear, at least for me, that `cfg` prefixes are unnecessary, verbose and redundant. Again, everything is just a proposal to move things forward. If the shown syntax isn't ideal, feel free to close this PR or suggest other alternatives.
2 parents d8a6409 + c89f0dc commit fca1481

File tree

7 files changed

+528
-21
lines changed

7 files changed

+528
-21
lines changed

compiler/rustc_data_structures/src/flock.rs

+25
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! green/native threading. This is just a bare-bones enough solution for
55
//! librustdoc, it is not production quality at all.
66
7+
#[cfg(bootstrap)]
78
cfg_match! {
89
cfg(target_os = "linux") => {
910
mod linux;
@@ -27,4 +28,28 @@ cfg_match! {
2728
}
2829
}
2930

31+
#[cfg(not(bootstrap))]
32+
cfg_match! {
33+
target_os = "linux" => {
34+
mod linux;
35+
use linux as imp;
36+
}
37+
target_os = "redox" => {
38+
mod linux;
39+
use linux as imp;
40+
}
41+
unix => {
42+
mod unix;
43+
use unix as imp;
44+
}
45+
windows => {
46+
mod windows;
47+
use self::windows as imp;
48+
}
49+
_ => {
50+
mod unsupported;
51+
use unsupported as imp;
52+
}
53+
}
54+
3055
pub use imp::Lock;

compiler/rustc_data_structures/src/profiling.rs

+63
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ fn get_thread_id() -> u32 {
860860
}
861861

862862
// Memory reporting
863+
#[cfg(bootstrap)]
863864
cfg_match! {
864865
cfg(windows) => {
865866
pub fn get_resident_set_size() -> Option<usize> {
@@ -921,5 +922,67 @@ cfg_match! {
921922
}
922923
}
923924

925+
#[cfg(not(bootstrap))]
926+
cfg_match! {
927+
windows => {
928+
pub fn get_resident_set_size() -> Option<usize> {
929+
use std::mem;
930+
931+
use windows::{
932+
Win32::System::ProcessStatus::{K32GetProcessMemoryInfo, PROCESS_MEMORY_COUNTERS},
933+
Win32::System::Threading::GetCurrentProcess,
934+
};
935+
936+
let mut pmc = PROCESS_MEMORY_COUNTERS::default();
937+
let pmc_size = mem::size_of_val(&pmc);
938+
unsafe {
939+
K32GetProcessMemoryInfo(
940+
GetCurrentProcess(),
941+
&mut pmc,
942+
pmc_size as u32,
943+
)
944+
}
945+
.ok()
946+
.ok()?;
947+
948+
Some(pmc.WorkingSetSize)
949+
}
950+
}
951+
target_os = "macos" => {
952+
pub fn get_resident_set_size() -> Option<usize> {
953+
use libc::{c_int, c_void, getpid, proc_pidinfo, proc_taskinfo, PROC_PIDTASKINFO};
954+
use std::mem;
955+
const PROC_TASKINFO_SIZE: c_int = mem::size_of::<proc_taskinfo>() as c_int;
956+
957+
unsafe {
958+
let mut info: proc_taskinfo = mem::zeroed();
959+
let info_ptr = &mut info as *mut proc_taskinfo as *mut c_void;
960+
let pid = getpid() as c_int;
961+
let ret = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, info_ptr, PROC_TASKINFO_SIZE);
962+
if ret == PROC_TASKINFO_SIZE {
963+
Some(info.pti_resident_size as usize)
964+
} else {
965+
None
966+
}
967+
}
968+
}
969+
}
970+
unix => {
971+
pub fn get_resident_set_size() -> Option<usize> {
972+
let field = 1;
973+
let contents = fs::read("/proc/self/statm").ok()?;
974+
let contents = String::from_utf8(contents).ok()?;
975+
let s = contents.split_whitespace().nth(field)?;
976+
let npages = s.parse::<usize>().ok()?;
977+
Some(npages * 4096)
978+
}
979+
}
980+
_ => {
981+
pub fn get_resident_set_size() -> Option<usize> {
982+
None
983+
}
984+
}
985+
}
986+
924987
#[cfg(test)]
925988
mod tests;

compiler/rustc_span/src/analyze_source_file.rs

+160
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub(crate) fn analyze_source_file(src: &str) -> (Vec<RelativeBytePos>, Vec<Multi
2929
(lines, multi_byte_chars)
3030
}
3131

32+
#[cfg(bootstrap)]
3233
cfg_match! {
3334
cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
3435
fn analyze_source_file_dispatch(
@@ -185,6 +186,165 @@ cfg_match! {
185186
}
186187
}
187188
}
189+
190+
#[cfg(not(bootstrap))]
191+
cfg_match! {
192+
any(target_arch = "x86", target_arch = "x86_64") => {
193+
fn analyze_source_file_dispatch(
194+
src: &str,
195+
lines: &mut Vec<RelativeBytePos>,
196+
multi_byte_chars: &mut Vec<MultiByteChar>,
197+
) {
198+
if is_x86_feature_detected!("sse2") {
199+
unsafe {
200+
analyze_source_file_sse2(src, lines, multi_byte_chars);
201+
}
202+
} else {
203+
analyze_source_file_generic(
204+
src,
205+
src.len(),
206+
RelativeBytePos::from_u32(0),
207+
lines,
208+
multi_byte_chars,
209+
);
210+
}
211+
}
212+
213+
/// Checks 16 byte chunks of text at a time. If the chunk contains
214+
/// something other than printable ASCII characters and newlines, the
215+
/// function falls back to the generic implementation. Otherwise it uses
216+
/// SSE2 intrinsics to quickly find all newlines.
217+
#[target_feature(enable = "sse2")]
218+
unsafe fn analyze_source_file_sse2(
219+
src: &str,
220+
lines: &mut Vec<RelativeBytePos>,
221+
multi_byte_chars: &mut Vec<MultiByteChar>,
222+
) {
223+
#[cfg(target_arch = "x86")]
224+
use std::arch::x86::*;
225+
#[cfg(target_arch = "x86_64")]
226+
use std::arch::x86_64::*;
227+
228+
const CHUNK_SIZE: usize = 16;
229+
230+
let src_bytes = src.as_bytes();
231+
232+
let chunk_count = src.len() / CHUNK_SIZE;
233+
234+
// This variable keeps track of where we should start decoding a
235+
// chunk. If a multi-byte character spans across chunk boundaries,
236+
// we need to skip that part in the next chunk because we already
237+
// handled it.
238+
let mut intra_chunk_offset = 0;
239+
240+
for chunk_index in 0..chunk_count {
241+
let ptr = src_bytes.as_ptr() as *const __m128i;
242+
// We don't know if the pointer is aligned to 16 bytes, so we
243+
// use `loadu`, which supports unaligned loading.
244+
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
245+
246+
// For character in the chunk, see if its byte value is < 0, which
247+
// indicates that it's part of a UTF-8 char.
248+
let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
249+
// Create a bit mask from the comparison results.
250+
let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };
251+
252+
// If the bit mask is all zero, we only have ASCII chars here:
253+
if multibyte_mask == 0 {
254+
assert!(intra_chunk_offset == 0);
255+
256+
// Check if there are any control characters in the chunk. All
257+
// control characters that we can encounter at this point have a
258+
// byte value less than 32 or ...
259+
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
260+
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
261+
262+
// ... it's the ASCII 'DEL' character with a value of 127.
263+
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
264+
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
265+
266+
let control_char_mask = control_char_mask0 | control_char_mask1;
267+
268+
if control_char_mask != 0 {
269+
// Check for newlines in the chunk
270+
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
271+
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
272+
273+
if control_char_mask == newlines_mask {
274+
// All control characters are newlines, record them
275+
let mut newlines_mask = 0xFFFF0000 | newlines_mask as u32;
276+
let output_offset = RelativeBytePos::from_usize(chunk_index * CHUNK_SIZE + 1);
277+
278+
loop {
279+
let index = newlines_mask.trailing_zeros();
280+
281+
if index >= CHUNK_SIZE as u32 {
282+
// We have arrived at the end of the chunk.
283+
break;
284+
}
285+
286+
lines.push(RelativeBytePos(index) + output_offset);
287+
288+
// Clear the bit, so we can find the next one.
289+
newlines_mask &= (!1) << index;
290+
}
291+
292+
// We are done for this chunk. All control characters were
293+
// newlines and we took care of those.
294+
continue;
295+
} else {
296+
// Some of the control characters are not newlines,
297+
// fall through to the slow path below.
298+
}
299+
} else {
300+
// No control characters, nothing to record for this chunk
301+
continue;
302+
}
303+
}
304+
305+
// The slow path.
306+
// There are control chars in here, fallback to generic decoding.
307+
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
308+
intra_chunk_offset = analyze_source_file_generic(
309+
&src[scan_start..],
310+
CHUNK_SIZE - intra_chunk_offset,
311+
RelativeBytePos::from_usize(scan_start),
312+
lines,
313+
multi_byte_chars,
314+
);
315+
}
316+
317+
// There might still be a tail left to analyze
318+
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
319+
if tail_start < src.len() {
320+
analyze_source_file_generic(
321+
&src[tail_start..],
322+
src.len() - tail_start,
323+
RelativeBytePos::from_usize(tail_start),
324+
lines,
325+
multi_byte_chars,
326+
);
327+
}
328+
}
329+
}
330+
_ => {
331+
// The target (or compiler version) does not support SSE2 ...
332+
fn analyze_source_file_dispatch(
333+
src: &str,
334+
lines: &mut Vec<RelativeBytePos>,
335+
multi_byte_chars: &mut Vec<MultiByteChar>,
336+
) {
337+
analyze_source_file_generic(
338+
src,
339+
src.len(),
340+
RelativeBytePos::from_u32(0),
341+
lines,
342+
multi_byte_chars,
343+
);
344+
}
345+
}
346+
}
347+
188348
// `scan_len` determines the number of bytes in `src` to scan. Note that the
189349
// function can read past `scan_len` if a multi-byte character start within the
190350
// range but extends past it. The overflow is returned by the function.

library/core/src/macros/mod.rs

+52
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub macro assert_matches {
224224
/// }
225225
/// }
226226
/// ```
227+
#[cfg(bootstrap)]
227228
#[unstable(feature = "cfg_match", issue = "115585")]
228229
#[rustc_diagnostic_item = "cfg_match"]
229230
pub macro cfg_match {
@@ -284,6 +285,57 @@ pub macro cfg_match {
284285
}
285286
}
286287

288+
/// A macro for defining `#[cfg]` match-like statements.
289+
///
290+
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
291+
/// `#[cfg]` cases, emitting the implementation which matches first.
292+
///
293+
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
294+
/// without having to rewrite each clause multiple times.
295+
///
296+
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
297+
/// all previous declarations do not evaluate to true.
298+
///
299+
/// # Example
300+
///
301+
/// ```
302+
/// #![feature(cfg_match)]
303+
///
304+
/// cfg_match! {
305+
/// unix => {
306+
/// fn foo() { /* unix specific functionality */ }
307+
/// }
308+
/// target_pointer_width = "32" => {
309+
/// fn foo() { /* non-unix, 32-bit functionality */ }
310+
/// }
311+
/// _ => {
312+
/// fn foo() { /* fallback implementation */ }
313+
/// }
314+
/// }
315+
/// ```
316+
#[cfg(not(bootstrap))]
317+
#[unstable(feature = "cfg_match", issue = "115585")]
318+
#[rustc_diagnostic_item = "cfg_match"]
319+
pub macro cfg_match {
320+
({ $($tt:tt)* }) => {{
321+
cfg_match! { $($tt)* }
322+
}},
323+
(_ => { $($output:tt)* }) => {
324+
$($output)*
325+
},
326+
(
327+
$cfg:meta => $output:tt
328+
$($( $rest:tt )+)?
329+
) => {
330+
#[cfg($cfg)]
331+
cfg_match! { _ => $output }
332+
$(
333+
#[cfg(not($cfg))]
334+
cfg_match! { $($rest)+ }
335+
)?
336+
},
337+
}
338+
287339
/// Asserts that a boolean expression is `true` at runtime.
288340
///
289341
/// This will invoke the [`panic!`] macro if the provided expression cannot be

library/core/tests/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,10 @@ mod intrinsics;
153153
mod io;
154154
mod iter;
155155
mod lazy;
156+
#[cfg(not(bootstrap))]
156157
mod macros;
158+
#[cfg(bootstrap)]
159+
mod macros_bootstrap;
157160
mod manually_drop;
158161
mod mem;
159162
mod net;

0 commit comments

Comments
 (0)