diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 6cdb7f2..94ed5ee 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -12,13 +12,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup component add clippy + run: rustup show - uses: Swatinem/rust-cache@v2 - # FIXME: enable once there is code - # - run: cargo clippy --all-features --all-targets -- -D warnings + - name: Install packages + run: | + sudo apt-get install llvm-14-tools + - run: cargo clippy --manifest-path crates/Cargo.toml --all-features --all-targets -- -D warnings test: name: test @@ -26,38 +25,38 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - rustup component add clippy + run: rustup show - uses: Swatinem/rust-cache@v2 - # FIXME: enable once there is code - # - run: cargo test + - name: Install packages + run: | + sudo apt-get install llvm-14-tools + - run: ./y test rustfmt: name: rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v4 - name: Install Rust + run: rustup show + - uses: Swatinem/rust-cache@v2 + - name: Install packages run: | - rustup update nightly --no-self-update - rustup default nightly - rustup component add rustfmt - # FIXME: enable once there is code - # - run: cargo fmt --all -- --check + sudo apt-get install llvm-14-tools + - run: ./y fmt --check doc: name: docs runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - run: | - rustup update nightly --no-self-update - rustup default nightly + - name: Install Rust + run: rustup show - uses: Swatinem/rust-cache@v2 - # FIXME: enable once there is code - # - run: cargo doc + - name: Install packages + run: | + sudo apt-get install llvm-14-tools + - run: cargo doc --manifest-path crates/Cargo.toml success: needs: diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c40ed2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build +rustc-ice-* diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..79c9b5d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "rust-analyzer.rustc.source": "discover", + "rust-analyzer.workspace.symbol.search.scope": "workspace_and_dependencies", + "rust-analyzer.linkedProjects": [ + "./crates/Cargo.toml", + "./bootstrap/Cargo.toml", + ] +} diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/bootstrap/.gitignore @@ -0,0 +1 @@ +/target diff --git a/bootstrap/Cargo.lock b/bootstrap/Cargo.lock new file mode 100644 index 0000000..698bdbd --- /dev/null +++ b/bootstrap/Cargo.lock @@ -0,0 +1,439 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "clap" +version = "4.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "color-print" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0" +dependencies = [ + "color-print-proc-macro", +] + +[[package]] +name = "color-print-proc-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93" +dependencies = [ + "nom", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "env_filter" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "which" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" +dependencies = [ + "either", + "home", + "rustix", + "winsafe", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "y" +version = "0.0.0" +dependencies = [ + "anstream", + "clap", + "color-print", + "env_logger", + "glob", + "log", + "which", +] diff --git a/bootstrap/Cargo.toml b/bootstrap/Cargo.toml new file mode 100644 index 0000000..3c61ecd --- /dev/null +++ b/bootstrap/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "y" +edition = "2021" +publish = false + +[dependencies] +anstream = "0.6.14" +clap = { version = "4.5.9", features = ["derive"] } +color-print = "0.3.6" +env_logger = "0.11.5" +glob = "0.3.1" +log = "0.4.22" +which = "6.0.1" diff --git a/bootstrap/src/clean.rs b/bootstrap/src/clean.rs new file mode 100644 index 0000000..1f8a5f9 --- /dev/null +++ b/bootstrap/src/clean.rs @@ -0,0 +1,14 @@ +use clap::Args; + +use crate::{manifest::Manifest, Run}; + +/// Clean the build directory +#[derive(Args, Debug)] +pub struct CleanCommand {} + +impl Run for CleanCommand { + fn run(&self, manifest: &Manifest) { + let _ = std::fs::remove_dir_all("crates/target"); + let _ = std::fs::remove_dir_all(&manifest.out_dir); + } +} diff --git a/bootstrap/src/fmt.rs b/bootstrap/src/fmt.rs new file mode 100644 index 0000000..93e2f4e --- /dev/null +++ b/bootstrap/src/fmt.rs @@ -0,0 +1,57 @@ +use std::process::Command; + +use clap::Args; +use glob::glob; + +use crate::Run; + +/// Format code, examples and tests +#[derive(Args, Debug)] +pub struct FmtCommand { + #[arg(short, long)] + pub check: bool, +} + +impl Run for FmtCommand { + fn run(&self, _manifest: &crate::manifest::Manifest) { + self.perform( + Command::new("cargo") + .arg("fmt") + .args(["--manifest-path", "bootstrap/Cargo.toml"]), + ); + self.perform( + Command::new("cargo") + .arg("fmt") + .args(["--manifest-path", "crates/Cargo.toml"]) + .arg("--all"), + ); + for file in glob("example/**/*.rs").unwrap() { + self.perform( + Command::new("rustfmt") + .args(["--edition", "2021"]) + .arg(file.unwrap()), + ); + } + for file in glob("tests/**/*.rs").unwrap() { + self.perform( + Command::new("rustfmt") + .args(["--edition", "2021"]) + .arg(file.unwrap()), + ); + } + } +} + +impl FmtCommand { + pub fn perform(&self, command: &mut Command) { + if self.check { + command.arg("--check"); + } + log::debug!("running {:?}", command); + assert!( + command.status().unwrap().success(), + "failed to run {:?}", + command + ); + } +} diff --git a/bootstrap/src/main.rs b/bootstrap/src/main.rs new file mode 100644 index 0000000..c8a1e5d --- /dev/null +++ b/bootstrap/src/main.rs @@ -0,0 +1,58 @@ +use clap::{Parser, Subcommand}; + +use crate::manifest::Manifest; + +mod clean; +mod fmt; +mod manifest; +mod rustc; +mod test; + +/// Bootstrap system for the rustc codegen c +#[derive(Parser, Debug)] +#[command(about, long_about = None)] +pub struct Cli { + /// Build the codegen backend in release mode + #[arg(short, long)] + pub release: bool, + + /// The output directory + #[arg(short, long)] + pub out_dir: Option, + + /// verbose output + #[arg(short, long)] + pub verbose: bool, + + #[command(subcommand)] + pub command: Command, +} + +#[derive(Subcommand, Debug)] +pub enum Command { + Test(test::TestCommand), + Clean(clean::CleanCommand), + Rustc(rustc::RustcCommand), + Fmt(fmt::FmtCommand), +} + +trait Run { + fn run(&self, manifest: &Manifest); +} + +fn main() { + env_logger::init(); + let cli = Cli::parse(); + + let manifest = Manifest { + verbose: cli.verbose, + release: cli.release, + out_dir: cli.out_dir.unwrap_or("build".to_string()).into(), + }; + match cli.command { + Command::Test(test) => test.run(&manifest), + Command::Clean(clean) => clean.run(&manifest), + Command::Rustc(rustc) => rustc.run(&manifest), + Command::Fmt(fmt) => fmt.run(&manifest), + } +} diff --git a/bootstrap/src/manifest.rs b/bootstrap/src/manifest.rs new file mode 100644 index 0000000..61e6efa --- /dev/null +++ b/bootstrap/src/manifest.rs @@ -0,0 +1,79 @@ +use anstream::eprintln as println; +use color_print::cprintln; +use std::path::{Path, PathBuf}; +use std::process::Command; + +pub struct Manifest { + pub verbose: bool, + pub release: bool, + pub out_dir: PathBuf, +} + +impl Manifest { + /// Builds the rustc codegen c library + pub fn prepare(&self) { + cprintln!("[BUILD] codegen backend"); + let mut command = Command::new("cargo"); + command + .arg("build") + .args(["--manifest-path", "crates/Cargo.toml"]); + if self.verbose { + command.args(["-F", "debug"]); + } + if self.release { + command.arg("--release"); + } + log::debug!("running {:?}", command); + command.status().unwrap(); + + cprintln!("[BUILD] librust_runtime"); + std::fs::create_dir_all(&self.out_dir).unwrap(); + let cc = std::env::var("CC").unwrap_or("clang".to_string()); + let mut command = Command::new(&cc); + command + .arg("rust_runtime/rust_runtime.c") + .arg("-o") + .arg(self.out_dir.join("rust_runtime.o")) + .arg("-c"); + log::debug!("running {:?}", command); + command.status().unwrap(); + let mut command = Command::new("ar"); + command + .arg("rcs") + .arg(self.out_dir.join("librust_runtime.a")) + .arg(self.out_dir.join("rust_runtime.o")); + log::debug!("running {:?}", command); + command.status().unwrap(); + } + + /// The path to the rustc codegen c library + pub fn codegen_backend(&self) -> &'static Path { + if self.release { + Path::new("crates/target/release/librustc_codegen_c.so") + } else { + Path::new("crates/target/debug/librustc_codegen_c.so") + } + } + + /// The command to run rustc with the codegen backend + pub fn rustc(&self) -> Command { + let mut command = Command::new("rustc"); + command + .args(["--edition", "2021"]) + .arg("-Z") + .arg(format!( + "codegen-backend={}", + self.codegen_backend().display() + )) + .args(["-C", "panic=abort"]) + .args(["-C", "lto=false"]) + .arg(format!("-Lall={}", self.out_dir.display())) + .env("CFLAGS", "-Irust_runtime") + .arg("-lc") + .arg("-lrust_runtime"); + if self.verbose { + command.env("RUST_BACKTRACE", "full"); + } + command + } +} diff --git a/bootstrap/src/rustc.rs b/bootstrap/src/rustc.rs new file mode 100644 index 0000000..0c84e39 --- /dev/null +++ b/bootstrap/src/rustc.rs @@ -0,0 +1,30 @@ +use std::path::PathBuf; + +use clap::Args; + +use crate::{manifest::Manifest, Run}; + +/// Invoke rustc +#[derive(Args, Debug)] +pub struct RustcCommand { + source: PathBuf, + + #[arg(last = true)] + slop: Vec, +} + +impl Run for RustcCommand { + fn run(&self, manifest: &Manifest) { + manifest.prepare(); + + let mut command = manifest.rustc(); + command + .arg(&self.source) + .args(["--crate-type", "bin"]) + .arg("--out-dir") + .arg(&manifest.out_dir) + .args(&self.slop); + log::debug!("running {:?}", command); + command.status().unwrap(); + } +} diff --git a/bootstrap/src/test.rs b/bootstrap/src/test.rs new file mode 100644 index 0000000..243f73f --- /dev/null +++ b/bootstrap/src/test.rs @@ -0,0 +1,156 @@ +use std::fs::File; +use std::path::{Path, PathBuf}; + +use anstream::{eprint as print, eprintln as println}; +use clap::Args; +use color_print::{cprint, cprintln}; +use glob::glob; +use which::which; + +use crate::{manifest::Manifest, Run}; + +/// Run tests +#[derive(Args, Debug)] +pub struct TestCommand {} + +impl Run for TestCommand { + fn run(&self, manifest: &Manifest) { + manifest.prepare(); + + std::panic::set_hook(Box::new(|info| { + cprintln!("Test failed: {}", info); + })); + + let testcases = self.collect_testcases(manifest); + cprintln!("[TEST] found {} testcases", testcases.len()); + + let filechecker = FileChecker::new(); + for testcase in testcases { + match testcase.test { + TestType::FileCheck => { + cprint!("File checking {}...", testcase.name); + testcase.build(manifest); + filechecker.run(&testcase.source, &testcase.output); + } + TestType::Compile => { + cprint!("Compiling {}...", testcase.name); + testcase.build(manifest); + } + } + cprintln!("OK"); + } + } +} + +impl TestCommand { + pub fn collect_testcases(&self, manifest: &Manifest) -> Vec { + let mut result = vec![]; + + // Examples + for case in glob("example/*.rs").unwrap() { + let case = case.unwrap(); + let filename = case.file_stem().unwrap(); + if filename == "mini_core" { + continue; + } + let name = format!("example/{}", filename.to_string_lossy()); + let output = manifest.out_dir.join("example").join(filename); + result.push(TestCase { + name, + source: case, + output, + test: TestType::Compile, + }) + } + + // Codegen tests + for case in glob("tests/codegen/*.rs").unwrap() { + let case = case.unwrap(); + let filename = case.file_stem().unwrap(); + let name = format!("codegen/{}", filename.to_string_lossy()); + let output = manifest.out_dir.join("tests/codegen").join(filename); + result.push(TestCase { + name, + source: case, + output, + test: TestType::FileCheck, + }) + } + + result + } +} + +pub enum TestType { + Compile, + FileCheck, +} + +pub struct TestCase { + pub name: String, + pub source: PathBuf, + pub output: PathBuf, + pub test: TestType, +} + +impl TestCase { + pub fn build(&self, manifest: &Manifest) { + std::fs::create_dir_all(self.output.parent().unwrap()).unwrap(); + let mut command = manifest.rustc(); + command + .args(["--crate-type", "bin"]) + .arg("-O") + .arg(&self.source) + .arg("-o") + .arg(&self.output); + log::debug!("running {:?}", command); + command.status().unwrap(); + } +} + +struct FileChecker { + filecheck: PathBuf, +} + +impl FileChecker { + pub fn new() -> Self { + let filecheck = [ + "FileCheck-18", + "FileCheck-17", + "FileCheck-16", + "FileCheck-15", + "FileCheck-14", + "FileCheck", + ] + .into_iter() + .find_map(|filecheck| which(filecheck).ok()) + .expect("`FileCheck` not found"); + + Self { filecheck } + } + + fn run(&self, source: &Path, output: &Path) { + let case = source.file_stem().unwrap().to_string_lossy(); + let generated = std::fs::read_dir(output.parent().unwrap()) + .unwrap() + .filter_map(|entry| entry.ok()) + .find(|entry| { + let filename = entry.file_name(); + let filename = filename.to_string_lossy(); + filename.ends_with(".c") && filename.starts_with(case.as_ref()) + }); + + assert!( + generated.is_some(), + "could not find {case}'s generated file" + ); + let generated = generated.unwrap(); + + let generated = File::open(generated.path()).unwrap(); + let mut command = std::process::Command::new(&self.filecheck); + command.arg(source).stdin(generated); + log::debug!("running {:?}", command); + let output = command.output().unwrap(); + assert!(output.status.success(), "failed to run FileCheck on {case}"); + } +} diff --git a/compile_flags.txt b/compile_flags.txt new file mode 100644 index 0000000..c9be6c4 --- /dev/null +++ b/compile_flags.txt @@ -0,0 +1,3 @@ +--std=c99 +-I +rust_runtime diff --git a/crates/.gitignore b/crates/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/crates/.gitignore @@ -0,0 +1 @@ +/target diff --git a/crates/Cargo.lock b/crates/Cargo.lock new file mode 100644 index 0000000..aad4464 --- /dev/null +++ b/crates/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "rustc_codegen_c" +version = "0.1.0" diff --git a/crates/Cargo.toml b/crates/Cargo.toml new file mode 100644 index 0000000..8d7c0ce --- /dev/null +++ b/crates/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +resolver = "2" +members = ["rustc_codegen_c"] + +[workspace.package] +version = "0.1.0" diff --git a/crates/rustc_codegen_c/Cargo.toml b/crates/rustc_codegen_c/Cargo.toml new file mode 100644 index 0000000..98d3d36 --- /dev/null +++ b/crates/rustc_codegen_c/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rustc_codegen_c" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["dylib"] + +[dependencies] + +# This package uses rustc crates. +[package.metadata.rust-analyzer] +rustc_private=true diff --git a/crates/rustc_codegen_c/messages.ftl b/crates/rustc_codegen_c/messages.ftl new file mode 100644 index 0000000..e69de29 diff --git a/crates/rustc_codegen_c/src/archive.rs b/crates/rustc_codegen_c/src/archive.rs new file mode 100644 index 0000000..c6aff39 --- /dev/null +++ b/crates/rustc_codegen_c/src/archive.rs @@ -0,0 +1,27 @@ +//! from rustc_codegen_cranelift + +use std::path::{Path, PathBuf}; + +use rustc_codegen_ssa::back::archive::{ + get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, +}; +use rustc_session::Session; + +pub(crate) struct ArArchiveBuilderBuilder; + +impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder { + fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box { + Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols)) + } + + fn create_dll_import_lib( + &self, + _sess: &Session, + _lib_name: &str, + _dll_imports: &[rustc_session::cstore::DllImport], + _tmpdir: &Path, + _is_direct_dependency: bool, + ) -> PathBuf { + unimplemented!("creating dll imports is not yet supported"); + } +} diff --git a/crates/rustc_codegen_c/src/base.rs b/crates/rustc_codegen_c/src/base.rs new file mode 100644 index 0000000..354ba2f --- /dev/null +++ b/crates/rustc_codegen_c/src/base.rs @@ -0,0 +1,9 @@ +use rustc_codegen_ssa::ModuleCodegen; +use rustc_middle::ty::TyCtxt; + +pub fn compile_codegen_unit( + _tcx: TyCtxt<'_>, + _cgu_name: rustc_span::Symbol, +) -> (ModuleCodegen<()>, u64) { + todo!() +} diff --git a/crates/rustc_codegen_c/src/lib.rs b/crates/rustc_codegen_c/src/lib.rs new file mode 100644 index 0000000..9f90f7e --- /dev/null +++ b/crates/rustc_codegen_c/src/lib.rs @@ -0,0 +1,248 @@ +#![feature(rustc_private)] + +extern crate rustc_ast; +extern crate rustc_codegen_ssa; +extern crate rustc_data_structures; +extern crate rustc_driver; +extern crate rustc_errors; +extern crate rustc_fluent_macro; +extern crate rustc_metadata; +extern crate rustc_middle; +extern crate rustc_session; +extern crate rustc_span; + +use std::sync::Arc; + +use rustc_ast::expand::allocator::AllocatorKind; +use rustc_codegen_ssa::back::link::link_binary; +use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; +use rustc_codegen_ssa::back::write::{ + CodegenContext, FatLtoInput, ModuleConfig, OngoingCodegen, TargetMachineFactoryFn, +}; +use rustc_codegen_ssa::base::codegen_crate; +pub use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_codegen_ssa::traits::{ + ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods, +}; +use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::{DiagCtxtHandle, FatalError}; +use rustc_metadata::EncodedMetadata; +use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::ty::TyCtxt; +use rustc_middle::util::Providers; +use rustc_session::config::{OptLevel, OutputFilenames}; +use rustc_session::Session; +use rustc_span::ErrorGuaranteed; + +mod archive; +mod base; +mod util; +mod write; + +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } + +#[derive(Clone)] +pub struct CCodegen {} + +impl CodegenBackend for CCodegen { + fn locale_resource(&self) -> &'static str { + crate::DEFAULT_LOCALE_RESOURCE + } + + fn provide(&self, providers: &mut Providers) { + providers.global_backend_features = |tcx, ()| util::global_backend_features(tcx) + } + + fn codegen_crate( + &self, + tcx: TyCtxt<'_>, + metadata: EncodedMetadata, + need_metadata_module: bool, + ) -> Box { + let target_cpu = match tcx.sess.opts.cg.target_cpu { + Some(ref name) => name, + None => tcx.sess.target.cpu.as_ref(), + } + .to_owned(); + + let ongoing_codegen = codegen_crate( + self.clone(), + tcx, + target_cpu, + metadata, + need_metadata_module, + ); + Box::new(ongoing_codegen) + } + + fn join_codegen( + &self, + ongoing_codegen: Box, + sess: &Session, + _outputs: &OutputFilenames, + ) -> (CodegenResults, FxIndexMap) { + ongoing_codegen + .downcast::>() + .expect("expected CCodegen") + .join(sess) + } + + fn link( + &self, + sess: &Session, + codegen_results: CodegenResults, + outputs: &OutputFilenames, + ) -> Result<(), ErrorGuaranteed> { + link_binary( + sess, + &crate::archive::ArArchiveBuilderBuilder, + &codegen_results, + outputs, + ) + } +} + +impl ExtraBackendMethods for CCodegen { + fn codegen_allocator( + &self, + _tcx: TyCtxt<'_>, + _module_name: &str, + _kind: AllocatorKind, + _alloc_error_handler_kind: AllocatorKind, + ) -> Self::Module { + todo!() + } + + fn compile_codegen_unit( + &self, + tcx: TyCtxt<'_>, + cgu_name: rustc_span::Symbol, + ) -> (ModuleCodegen, u64) { + base::compile_codegen_unit(tcx, cgu_name) + } + + fn target_machine_factory( + &self, + _sess: &Session, + _opt_level: OptLevel, + _target_features: &[String], + ) -> TargetMachineFactoryFn { + Arc::new(|_| Ok(())) + } +} + +pub struct ModuleBuffer; + +impl ModuleBufferMethods for ModuleBuffer { + fn data(&self) -> &[u8] { + unimplemented!() + } +} + +pub struct ThinBuffer; + +impl ThinBufferMethods for ThinBuffer { + fn data(&self) -> &[u8] { + unimplemented!() + } + + fn thin_link_data(&self) -> &[u8] { + unimplemented!() + } +} + +impl WriteBackendMethods for CCodegen { + type Module = (); + type TargetMachine = (); + type TargetMachineError = (); + type ModuleBuffer = ModuleBuffer; + type ThinData = (); + type ThinBuffer = ThinBuffer; + + fn run_link( + cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, + modules: Vec>, + ) -> Result, FatalError> { + write::link(cgcx, dcx, modules) + } + + fn run_fat_lto( + _cgcx: &CodegenContext, + _modules: Vec>, + _cached_modules: Vec<(SerializedModule, WorkProduct)>, + ) -> Result, FatalError> { + unimplemented!() + } + + fn run_thin_lto( + _cgcx: &CodegenContext, + _modules: Vec<(String, Self::ThinBuffer)>, + _cached_modules: Vec<( + SerializedModule, + rustc_middle::dep_graph::WorkProduct, + )>, + ) -> Result<(Vec>, Vec), rustc_errors::FatalError> { + unimplemented!() + } + + fn print_pass_timings(&self) { + unimplemented!() + } + + fn print_statistics(&self) { + unimplemented!() + } + + unsafe fn optimize( + _cgcx: &CodegenContext, + _dcx: DiagCtxtHandle<'_>, + _module: &ModuleCodegen, + _config: &ModuleConfig, + ) -> Result<(), FatalError> { + Ok(()) + } + + fn optimize_fat( + _cgcx: &CodegenContext, + _llmod: &mut ModuleCodegen, + ) -> Result<(), FatalError> { + unimplemented!() + } + + unsafe fn optimize_thin( + _cgcx: &CodegenContext, + _thin: ThinModule, + ) -> Result, FatalError> { + unimplemented!() + } + + unsafe fn codegen( + cgcx: &CodegenContext, + dcx: DiagCtxtHandle<'_>, + module: ModuleCodegen, + config: &ModuleConfig, + ) -> Result { + write::codegen(cgcx, dcx, module, config) + } + + fn prepare_thin( + _module: ModuleCodegen, + _want_summary: bool, + ) -> (String, Self::ThinBuffer) { + unimplemented!() + } + + fn serialize_module( + _module: rustc_codegen_ssa::ModuleCodegen, + ) -> (String, Self::ModuleBuffer) { + unimplemented!() + } +} + +/// This is the entrypoint for a hot plugged codegen backend. +#[no_mangle] +pub fn __rustc_codegen_backend() -> Box { + Box::new(CCodegen {}) +} diff --git a/crates/rustc_codegen_c/src/util.rs b/crates/rustc_codegen_c/src/util.rs new file mode 100644 index 0000000..e7859b0 --- /dev/null +++ b/crates/rustc_codegen_c/src/util.rs @@ -0,0 +1,5 @@ +use rustc_middle::ty::TyCtxt; + +pub fn global_backend_features(_tcx: TyCtxt<'_>) -> Vec { + vec![] +} diff --git a/crates/rustc_codegen_c/src/write.rs b/crates/rustc_codegen_c/src/write.rs new file mode 100644 index 0000000..c4e1195 --- /dev/null +++ b/crates/rustc_codegen_c/src/write.rs @@ -0,0 +1,20 @@ +use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig}; +use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; +use rustc_errors::{DiagCtxtHandle, FatalError}; + +pub(crate) unsafe fn codegen( + _cgcx: &CodegenContext, + _dcx: DiagCtxtHandle<'_>, + _module: ModuleCodegen<()>, + _config: &ModuleConfig, +) -> Result { + todo!() +} + +pub(crate) fn link( + _cgcx: &CodegenContext, + _dcx: DiagCtxtHandle<'_>, + mut _modules: Vec>, +) -> Result, FatalError> { + unimplemented!(); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..777ae17 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2024-07-01" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/rust_runtime/rust_runtime.c b/rust_runtime/rust_runtime.c new file mode 100644 index 0000000..d119162 --- /dev/null +++ b/rust_runtime/rust_runtime.c @@ -0,0 +1 @@ +#include "rust_runtime.h" diff --git a/rust_runtime/rust_runtime.h b/rust_runtime/rust_runtime.h new file mode 100644 index 0000000..723ac98 --- /dev/null +++ b/rust_runtime/rust_runtime.h @@ -0,0 +1,4 @@ +#ifndef RUST_RUNTIME_H +#define RUST_RUNTIME_H + +#endif diff --git a/y b/y new file mode 100755 index 0000000..5553a50 --- /dev/null +++ b/y @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e +echo "[BUILD] build system" 1>&2 +exec cargo run --manifest-path bootstrap/Cargo.toml -- "$@"