Skip to content

Commit f69d8fc

Browse files
committed
Merge branch 'master' into sync_from_rust_2025_06_02
2 parents f383b17 + 8efeb49 commit f69d8fc

26 files changed

+706
-120
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ jobs:
6464
- name: Set env
6565
run: |
6666
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
67-
echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
68-
echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
6967
7068
#- name: Cache rust repository
7169
## We only clone the rust repository for rustc tests
@@ -80,8 +78,7 @@ jobs:
8078
run: |
8179
./y.sh prepare --only-libcore
8280
./y.sh build --sysroot
83-
./y.sh test --mini-tests
84-
cargo test
81+
./y.sh test --cargo-tests
8582
8683
- name: Run y.sh cargo build
8784
run: |
@@ -115,6 +112,12 @@ jobs:
115112
- uses: actions/checkout@v4
116113
- run: python tools/check_intrinsics_duplicates.py
117114

115+
spell_check:
116+
runs-on: ubuntu-24.04
117+
steps:
118+
- uses: actions/checkout@v4
119+
- uses: crate-ci/typos@v1.32.0
120+
118121
build_system:
119122
runs-on: ubuntu-24.04
120123
steps:

.github/workflows/failures.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ jobs:
6666
run: |
6767
sudo dpkg --force-overwrite -i gcc-15.deb
6868
echo 'gcc-path = "/usr/lib"' > config.toml
69-
echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
70-
echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
69+
70+
7171
7272
- name: Set env
7373
run: |

.github/workflows/m68k.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ jobs:
6565
- name: Set env
6666
run: |
6767
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
68-
echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
69-
echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
68+
69+
7070
7171
#- name: Cache rust repository
7272
## We only clone the rust repository for rustc tests
@@ -95,7 +95,7 @@ jobs:
9595
./y.sh prepare --only-libcore --cross
9696
./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu
9797
./y.sh test --mini-tests
98-
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
98+
CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests
9999
./y.sh clean all
100100
101101
- name: Prepare dependencies

.github/workflows/release.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,14 @@ jobs:
4949
- name: Set env
5050
run: |
5151
echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
52-
echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
53-
echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
52+
53+
5454
5555
- name: Build
5656
run: |
5757
./y.sh prepare --only-libcore
5858
EMBED_LTO_BITCODE=1 ./y.sh build --sysroot --release --release-sysroot
59-
./y.sh test --mini-tests
60-
cargo test
59+
./y.sh test --cargo-tests
6160
./y.sh clean all
6261
6362
- name: Prepare dependencies

.github/workflows/stdarch.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ jobs:
9090
if: ${{ !matrix.cargo_runner }}
9191
run: |
9292
./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
93-
cargo test
93+
./y.sh test --cargo-tests
9494
9595
- name: Run stdarch tests
9696
if: ${{ !matrix.cargo_runner }}

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ tools/llvmint-2
1919
llvm
2020
build_system/target
2121
config.toml
22-
build
22+
build
23+
rustlantis

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ To run specific tests, use appropriate flags such as:
3333

3434
- `./y.sh test --test-libcore`
3535
- `./y.sh test --std-tests`
36-
- `cargo test -- <name of test>`
36+
- `./y.sh test --cargo-tests -- <name of test>`
3737

3838
Additionally, you can run the tests of `libgccjit`:
3939

_typos.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[default.extend-words]
2+
ba = "ba"
3+
hsa = "hsa"
4+
olt = "olt"
5+
seh = "seh"
6+
typ = "typ"
7+
8+
[files]
9+
extend-exclude = ["src/intrinsic/archs.rs"]

build_system/src/fuzz.rs

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
use std::ffi::OsStr;
2+
use std::path::Path;
3+
4+
use crate::utils::run_command_with_output;
5+
6+
fn show_usage() {
7+
println!(
8+
r#"
9+
`fuzz` command help:
10+
--help : Show this help"#
11+
);
12+
}
13+
14+
pub fn run() -> Result<(), String> {
15+
// We skip binary name and the `fuzz` command.
16+
let mut args = std::env::args().skip(2);
17+
let mut start = 0;
18+
let mut count = 100;
19+
let mut threads =
20+
std::thread::available_parallelism().map(|threads| threads.get()).unwrap_or(1);
21+
while let Some(arg) = args.next() {
22+
match arg.as_str() {
23+
"--help" => {
24+
show_usage();
25+
return Ok(());
26+
}
27+
"--start" => {
28+
start =
29+
str::parse(&args.next().ok_or_else(|| "Fuzz start not provided!".to_string())?)
30+
.map_err(|err| (format!("Fuzz start not a number {err:?}!")))?;
31+
}
32+
"--count" => {
33+
count =
34+
str::parse(&args.next().ok_or_else(|| "Fuzz count not provided!".to_string())?)
35+
.map_err(|err| (format!("Fuzz count not a number {err:?}!")))?;
36+
}
37+
"-j" | "--jobs" => {
38+
threads = str::parse(
39+
&args.next().ok_or_else(|| "Fuzz thread count not provided!".to_string())?,
40+
)
41+
.map_err(|err| (format!("Fuzz thread count not a number {err:?}!")))?;
42+
}
43+
_ => return Err(format!("Unknown option {}", arg)),
44+
}
45+
}
46+
47+
// Ensure that we have a cloned version of rustlantis on hand.
48+
crate::utils::git_clone(
49+
"https://github.com/cbeuw/rustlantis.git",
50+
Some("clones/rustlantis".as_ref()),
51+
true,
52+
)
53+
.map_err(|err| (format!("Git clone failed with message: {err:?}!")))?;
54+
55+
// Ensure that we are on the newest rustlantis commit.
56+
let cmd: &[&dyn AsRef<OsStr>] = &[&"git", &"pull", &"origin"];
57+
run_command_with_output(cmd, Some(&Path::new("clones/rustlantis")))?;
58+
59+
// Build the release version of rustlantis
60+
let cmd: &[&dyn AsRef<OsStr>] = &[&"cargo", &"build", &"--release"];
61+
run_command_with_output(cmd, Some(&Path::new("clones/rustlantis")))?;
62+
// Fuzz a given range
63+
fuzz_range(start, start + count, threads);
64+
Ok(())
65+
}
66+
67+
/// Fuzzes a range `start..end` with `threads`.
68+
fn fuzz_range(start: u64, end: u64, threads: usize) {
69+
use std::sync::Arc;
70+
use std::sync::atomic::{AtomicU64, Ordering};
71+
use std::time::{Duration, Instant};
72+
// Total amount of files to fuzz
73+
let total = end - start;
74+
// Currently fuzzed element
75+
let start = Arc::new(AtomicU64::new(start));
76+
// Count time during fuzzing
77+
let start_time = Instant::now();
78+
// Spawn `threads`..
79+
for _ in 0..threads {
80+
let start = start.clone();
81+
// .. which each will ..
82+
std::thread::spawn(move || {
83+
// ... grab the next fuzz seed ...
84+
while start.load(Ordering::Relaxed) < end {
85+
let next = start.fetch_add(1, Ordering::Relaxed);
86+
// .. test that seed .
87+
match test(next) {
88+
Err(err) => {
89+
// If the test failed at compile-time...
90+
println!("test({}) failed because {err:?}", next);
91+
// ... copy that file to the directory `target/fuzz/compiletime_error`...
92+
let mut out_path: std::path::PathBuf =
93+
"target/fuzz/compiletime_error".into();
94+
std::fs::create_dir_all(&out_path).unwrap();
95+
// .. into a file named `fuzz{seed}.rs`.
96+
out_path.push(&format!("fuzz{next}.rs"));
97+
std::fs::copy(err, out_path).unwrap();
98+
}
99+
Ok(Err(err)) => {
100+
// If the test failed at run-time...
101+
println!("The LLVM and GCC results don't match for {err:?}");
102+
// ... copy that file to the directory `target/fuzz/runtime_error`...
103+
let mut out_path: std::path::PathBuf = "target/fuzz/runtime_error".into();
104+
std::fs::create_dir_all(&out_path).unwrap();
105+
// .. into a file named `fuzz{seed}.rs`.
106+
out_path.push(&format!("fuzz{next}.rs"));
107+
std::fs::copy(err, out_path).unwrap();
108+
}
109+
// If the test passed, do nothing
110+
Ok(Ok(())) => (),
111+
}
112+
}
113+
});
114+
}
115+
// The "manager" thread loop.
116+
while start.load(Ordering::Relaxed) < end {
117+
// Every 500 ms...
118+
let five_hundred_millis = Duration::from_millis(500);
119+
std::thread::sleep(five_hundred_millis);
120+
// ... calculate the remaining fuzz iters ...
121+
let remaining = end - start.load(Ordering::Relaxed);
122+
// ... fix the count(the start counter counts the cases that
123+
// begun fuzzing, and not only the ones that are done)...
124+
let fuzzed = (total - remaining) - threads as u64;
125+
// ... and the fuzz speed ...
126+
let iter_per_sec = fuzzed as f64 / start_time.elapsed().as_secs_f64();
127+
// .. and use them to display fuzzing stats.
128+
println!(
129+
"fuzzed {fuzzed} cases({}%), at rate {iter_per_sec} iter/s, remaining ~{}s",
130+
(100 * fuzzed) as f64 / total as f64,
131+
(remaining as f64) / iter_per_sec
132+
)
133+
}
134+
}
135+
136+
/// Builds & runs a file with LLVM.
137+
fn debug_llvm(path: &std::path::Path) -> Result<Vec<u8>, String> {
138+
// Build a file named `llvm_elf`...
139+
let exe_path = path.with_extension("llvm_elf");
140+
// ... using the LLVM backend ...
141+
let output = std::process::Command::new("rustc")
142+
.arg(path)
143+
.arg("-o")
144+
.arg(&exe_path)
145+
.output()
146+
.map_err(|err| format!("{err:?}"))?;
147+
// ... check that the compilation succeeded ...
148+
if !output.status.success() {
149+
return Err(format!("LLVM compilation failed:{output:?}"));
150+
}
151+
// ... run the resulting executable ...
152+
let output =
153+
std::process::Command::new(&exe_path).output().map_err(|err| format!("{err:?}"))?;
154+
// ... check it run normally ...
155+
if !output.status.success() {
156+
return Err(format!(
157+
"The program at {path:?}, compiled with LLVM, exited unsuccessfully:{output:?}"
158+
));
159+
}
160+
// ... cleanup that executable ...
161+
std::fs::remove_file(exe_path).map_err(|err| format!("{err:?}"))?;
162+
// ... and return the output(stdout + stderr - this allows UB checks to fire).
163+
let mut res = output.stdout;
164+
res.extend(output.stderr);
165+
Ok(res)
166+
}
167+
168+
/// Builds & runs a file with GCC.
169+
fn release_gcc(path: &std::path::Path) -> Result<Vec<u8>, String> {
170+
// Build a file named `gcc_elf`...
171+
let exe_path = path.with_extension("gcc_elf");
172+
// ... using the GCC backend ...
173+
let output = std::process::Command::new("./y.sh")
174+
.arg("rustc")
175+
.arg(path)
176+
.arg("-O")
177+
.arg("-o")
178+
.arg(&exe_path)
179+
.output()
180+
.map_err(|err| format!("{err:?}"))?;
181+
// ... check that the compilation succeeded ...
182+
if !output.status.success() {
183+
return Err(format!("GCC compilation failed:{output:?}"));
184+
}
185+
// ... run the resulting executable ..
186+
let output =
187+
std::process::Command::new(&exe_path).output().map_err(|err| format!("{err:?}"))?;
188+
// ... check it run normally ...
189+
if !output.status.success() {
190+
return Err(format!(
191+
"The program at {path:?}, compiled with GCC, exited unsuccessfully:{output:?}"
192+
));
193+
}
194+
// ... cleanup that executable ...
195+
std::fs::remove_file(exe_path).map_err(|err| format!("{err:?}"))?;
196+
// ... and return the output(stdout + stderr - this allows UB checks to fire).
197+
let mut res = output.stdout;
198+
res.extend(output.stderr);
199+
Ok(res)
200+
}
201+
202+
/// Generates a new rustlantis file, & compares the result of running it with GCC and LLVM.
203+
fn test(seed: u64) -> Result<Result<(), std::path::PathBuf>, String> {
204+
// Generate a Rust source...
205+
let source_file = generate(seed)?;
206+
// ... test it with debug LLVM ...
207+
let llvm_res = debug_llvm(&source_file)?;
208+
// ... test it with release GCC ...
209+
let gcc_res = release_gcc(&source_file)?;
210+
// ... compare the results ...
211+
if llvm_res != gcc_res {
212+
// .. if they don't match, report an error.
213+
Ok(Err(source_file))
214+
} else {
215+
std::fs::remove_file(source_file).map_err(|err| format!("{err:?}"))?;
216+
Ok(Ok(()))
217+
}
218+
}
219+
220+
/// Generates a new rustlantis file for us to run tests on.
221+
fn generate(seed: u64) -> Result<std::path::PathBuf, String> {
222+
use std::io::Write;
223+
let mut out_path = std::env::temp_dir();
224+
out_path.push(&format!("fuzz{seed}.rs"));
225+
// We need to get the command output here.
226+
let out = std::process::Command::new("cargo")
227+
.args(["run", "--release", "--bin", "generate"])
228+
.arg(&format!("{seed}"))
229+
.current_dir("clones/rustlantis")
230+
.output()
231+
.map_err(|err| format!("{err:?}"))?;
232+
// Stuff the rustlantis output in a source file.
233+
std::fs::File::create(&out_path)
234+
.map_err(|err| format!("{err:?}"))?
235+
.write_all(&out.stdout)
236+
.map_err(|err| format!("{err:?}"))?;
237+
Ok(out_path)
238+
}

build_system/src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod clean;
55
mod clone_gcc;
66
mod config;
77
mod fmt;
8+
mod fuzz;
89
mod info;
910
mod prepare;
1011
mod rust_tools;
@@ -42,7 +43,8 @@ Commands:
4243
test : Runs tests for the project.
4344
info : Displays information about the build environment and project configuration.
4445
clone-gcc : Clones the GCC compiler from a specified source.
45-
fmt : Runs rustfmt"
46+
fmt : Runs rustfmt
47+
fuzz : Fuzzes `cg_gcc` using rustlantis"
4648
);
4749
}
4850

@@ -56,6 +58,7 @@ pub enum Command {
5658
Test,
5759
Info,
5860
Fmt,
61+
Fuzz,
5962
}
6063

6164
fn main() {
@@ -75,6 +78,7 @@ fn main() {
7578
Some("info") => Command::Info,
7679
Some("clone-gcc") => Command::CloneGcc,
7780
Some("fmt") => Command::Fmt,
81+
Some("fuzz") => Command::Fuzz,
7882
Some("--help") => {
7983
usage();
8084
process::exit(0);
@@ -97,6 +101,7 @@ fn main() {
97101
Command::Info => info::run(),
98102
Command::CloneGcc => clone_gcc::run(),
99103
Command::Fmt => fmt::run(),
104+
Command::Fuzz => fuzz::run(),
100105
} {
101106
eprintln!("Command failed to run: {e}");
102107
process::exit(1);

0 commit comments

Comments
 (0)