diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2bfeeb29b..31062b4b44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,9 +32,17 @@ jobs: - name: Install Python Packages run: | + uv python install 3.14 + uv run python -V + uv venv uv pip install -r ./scripts/requirements.txt + # `zig cc` needed for cross-compilation + uv tool install ziglang + ln -s $(which python-zig) $(dirname $(which python-zig))/zig + zig version + # rust-cache very carefully caches toolchains and target directories, # based on the job and toolchain and other factors. See # https://github.com/Swatinem/rust-cache#cache-details for what gets @@ -47,6 +55,17 @@ jobs: # Run after `rust-cache` so that this is cached. - run: rustup component add rustfmt rustc-dev + - name: Install generated Rust targets + run: | + rustup +nightly-2023-04-15 target add \ + x86_64-unknown-linux-gnu \ + x86_64-apple-darwin \ + aarch64-unknown-linux-gnu \ + aarch64-apple-darwin \ + i686-unknown-linux-gnu \ + armv7-unknown-linux-gnueabihf \ + riscv64gc-unknown-linux-gnu + - name: cargo fmt --check run: | export RUSTFLAGS="$RUSTFLAGS -D warnings" @@ -98,7 +117,6 @@ jobs: # It's important that we keep `RUSTFLAGS` consistent between different steps # so that we don't have to rebuild everything. echo "RUSTFLAGS=-Clink-arg=-L/opt/homebrew/lib -Clink-arg=-Wl,-rpath,/opt/homebrew/lib" >> $GITHUB_ENV - - name: cargo build --release run: | diff --git a/Cargo.lock b/Cargo.lock index 7a734b069f..fddd742670 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,7 @@ dependencies = [ "serde_bytes", "serde_derive", "serde_json", + "shell-words", "smallvec", "strum", "strum_macros", @@ -2377,6 +2378,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.3.0" diff --git a/c2rust-transpile/Cargo.toml b/c2rust-transpile/Cargo.toml index fce3e7cbb4..8187fe4254 100644 --- a/c2rust-transpile/Cargo.toml +++ b/c2rust-transpile/Cargo.toml @@ -45,3 +45,4 @@ llvm-static = ["c2rust-ast-exporter/llvm-static"] [dev-dependencies] insta = { version = "1.43.2", features = ["glob"] } +shell-words = "1.1.0" diff --git a/c2rust-transpile/src/build_files/mod.rs b/c2rust-transpile/src/build_files/mod.rs index 5ab50d9a6b..80003422b5 100644 --- a/c2rust-transpile/src/build_files/mod.rs +++ b/c2rust-transpile/src/build_files/mod.rs @@ -2,7 +2,8 @@ use std::collections::BTreeMap; use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; -use std::str::FromStr; +use std::slice; +use std::str::{from_utf8, FromStr}; use handlebars::Handlebars; use pathdiff::diff_paths; @@ -225,7 +226,7 @@ fn emit_build_rs( }); let output = reg.render("build.rs", &json).unwrap(); let output_path = build_dir.join("build.rs"); - maybe_write_to_file(&output_path, output, tcfg.overwrite_existing) + maybe_write_to_file(&output_path, &output, tcfg.overwrite_existing) } /// Emit lib.rs (main.rs) for a library (binary). Returns `Some(path)` @@ -253,15 +254,68 @@ fn emit_lib_rs( let output_path = build_dir.join(file_name); let output = reg.render("lib.rs", &json).unwrap(); - maybe_write_to_file(&output_path, output, tcfg.overwrite_existing) + maybe_write_to_file(&output_path, &output, tcfg.overwrite_existing) } +pub const GENERATED_RUST_TOOLCHAIN_TOML: &str = include_str!("generated-rust-toolchain.toml"); +pub const GENERATED_RUST_TOOLCHAIN: &str = { + const fn find_substring(s: &str, sub: &str, start: usize) -> usize { + let s = s.as_bytes(); + let sub = sub.as_bytes(); + assert!(sub.len() + start <= s.len()); + let n = s.len() - sub.len(); + let mut i = start; + while i < n { + let mut j = 0; + let mut eq = true; + while j < sub.len() { + if s[i + j] != sub[j] { + eq = false; + break; + } + j += 1; + } + if eq { + return i; + } + i += 1; + } + assert!(false); + return 0; + } + + let toml = GENERATED_RUST_TOOLCHAIN_TOML; + let prefix = "\nchannel = \""; + let suffix = "\""; + let prefix_start = find_substring(toml, prefix, 0); + let start = prefix_start + prefix.len(); + let end = find_substring(toml, suffix, start); + + let toml = toml.as_bytes(); + let len = end - start; + assert!(start + len <= toml.len()); + // `const` slicing. + // SAFETY: Above `assert!`. + let toolchain = unsafe { + let ptr = toml.as_ptr().add(start); + slice::from_raw_parts(ptr, len) + }; + let toolchain = match from_utf8(toolchain) { + Ok(toolchain) => toolchain, + Err(_) => panic!(), + }; + toolchain +}; + /// If we translate variadic functions, the output will only compile /// on a nightly toolchain until the `c_variadics` feature is stable. fn emit_rust_toolchain(tcfg: &TranspilerConfig, build_dir: &Path) { let output_path = build_dir.join("rust-toolchain.toml"); - let output = include_str!("generated-rust-toolchain.toml").to_string(); - maybe_write_to_file(&output_path, output, tcfg.overwrite_existing); + maybe_write_to_file( + &output_path, + GENERATED_RUST_TOOLCHAIN_TOML, + tcfg.overwrite_existing, + ); } fn emit_cargo_toml<'lcmd>( @@ -306,10 +360,10 @@ fn emit_cargo_toml<'lcmd>( let file_name = "Cargo.toml"; let output_path = build_dir.join(file_name); let output = reg.render(file_name, &json).unwrap(); - maybe_write_to_file(&output_path, output, tcfg.overwrite_existing); + maybe_write_to_file(&output_path, &output, tcfg.overwrite_existing); } -fn maybe_write_to_file(output_path: &Path, output: String, overwrite: bool) -> Option { +fn maybe_write_to_file(output_path: &Path, output: &str, overwrite: bool) -> Option { if output_path.exists() && !overwrite { eprintln!("Skipping existing file {}", output_path.display()); return None; diff --git a/c2rust-transpile/src/lib.rs b/c2rust-transpile/src/lib.rs index e94ab9ecb8..b4385c5422 100644 --- a/c2rust-transpile/src/lib.rs +++ b/c2rust-transpile/src/lib.rs @@ -27,15 +27,15 @@ use regex::Regex; use serde_derive::Serialize; pub use tempfile::TempDir; +use crate::build_files::{emit_build_files, get_build_dir, CrateConfig}; +pub use crate::build_files::{GENERATED_RUST_TOOLCHAIN, GENERATED_RUST_TOOLCHAIN_TOML}; use crate::c_ast::Printer; use crate::c_ast::*; -pub use crate::diagnostics::Diagnostic; -use c2rust_ast_exporter as ast_exporter; - -use crate::build_files::{emit_build_files, get_build_dir, CrateConfig}; use crate::compile_cmds::get_compile_commands; use crate::convert_type::RESERVED_NAMES; +pub use crate::diagnostics::Diagnostic; pub use crate::translator::ReplaceMode; +use c2rust_ast_exporter as ast_exporter; use std::prelude::v1::Vec; type PragmaVec = Vec<(&'static str, Vec<&'static str>)>; diff --git a/c2rust-transpile/tests/snapshots.rs b/c2rust-transpile/tests/snapshots.rs index 0d9a59326f..475965fe57 100644 --- a/c2rust-transpile/tests/snapshots.rs +++ b/c2rust-transpile/tests/snapshots.rs @@ -1,9 +1,16 @@ +use std::borrow::Cow; +use std::collections::{HashMap, HashSet}; use std::env::current_dir; +use std::fmt::{self, Debug, Display, Formatter}; use std::fs; +use std::ops::Index; use std::path::Path; use std::process::Command; +use std::str::from_utf8; -use c2rust_transpile::{ReplaceMode, TranspilerConfig}; +use c2rust_transpile::{ReplaceMode, TranspilerConfig, GENERATED_RUST_TOOLCHAIN}; +use itertools::Itertools; +use tempfile::NamedTempFile; fn config() -> TranspilerConfig { TranspilerConfig { @@ -46,131 +53,557 @@ fn config() -> TranspilerConfig { } } -/// `platform` can be any platform-specific string. -/// It could be the `target_arch`, `target_os`, some combination, or something else. -fn transpile(platform: Option<&str>, c_path: &Path) { - let status = Command::new("clang") - .args([ +#[derive(Clone, Copy, PartialEq, Eq)] +enum Arch { + X86, + X86_64, + Arm, + AArch64, + RiscV64, +} + +impl Arch { + pub const fn name(&self) -> &'static str { + use Arch::*; + match *self { + X86 => "x86", + X86_64 => "x86_64", + Arm => "arm", + AArch64 => "aarch64", + RiscV64 => "riscv64", + } + } + + pub const fn ptr_width(&self) -> u8 { + use Arch::*; + match *self { + X86 | Arm => 32, + X86_64 | AArch64 | RiscV64 => 64, + } + } +} + +impl Display for Arch { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.name()) + } +} + +impl Debug for Arch { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.name()) + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Os { + Linux, + MacOs, +} + +impl Os { + pub const fn name(&self) -> &'static str { + use Os::*; + match *self { + Linux => "linux", + MacOs => "macos", + } + } +} + +impl Display for Os { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.name()) + } +} + +impl Debug for Os { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.name()) + } +} + +#[derive(Clone, Copy, PartialEq, Eq)] +enum Target { + X86_64UnknownLinuxGnu, + X86_64AppleDarwin, + AArch64UnknownLinuxGnu, + AArch64AppleDarwin, + I686UnknownLinuxGnu, + ArmV7UnknownLinuxGnueabihf, + RiscV64GcUnknownLinuxGnu, +} + +impl Target { + pub const ALL: &[Self] = &[ + Self::X86_64UnknownLinuxGnu, + Self::X86_64AppleDarwin, + Self::AArch64UnknownLinuxGnu, + Self::AArch64AppleDarwin, + Self::I686UnknownLinuxGnu, + Self::ArmV7UnknownLinuxGnueabihf, + Self::RiscV64GcUnknownLinuxGnu, + ]; + + pub const fn rust_name(&self) -> &'static str { + use Target::*; + match *self { + X86_64UnknownLinuxGnu => "x86_64-unknown-linux-gnu", + X86_64AppleDarwin => "x86_64-apple-darwin", + AArch64UnknownLinuxGnu => "aarch64-unknown-linux-gnu", + AArch64AppleDarwin => "aarch64-apple-darwin", + I686UnknownLinuxGnu => "i686-unknown-linux-gnu", + ArmV7UnknownLinuxGnueabihf => "armv7-unknown-linux-gnueabihf", + RiscV64GcUnknownLinuxGnu => "riscv64gc-unknown-linux-gnu", + } + } + + pub const fn clang_name(&self) -> &'static str { + use Target::*; + match *self { + RiscV64GcUnknownLinuxGnu => "riscv64-unknown-linux-gnu", + _ => self.rust_name(), + } + } + + pub const fn zig_name(&self) -> &'static str { + use Target::*; + match *self { + X86_64UnknownLinuxGnu => "x86_64-linux-gnu", + X86_64AppleDarwin => "x86_64-macos", + AArch64UnknownLinuxGnu => "aarch64-linux-gnu", + AArch64AppleDarwin => "aarch64-macos", + I686UnknownLinuxGnu => "x86-linux-gnu", + ArmV7UnknownLinuxGnueabihf => "arm-linux-gnueabihf", + RiscV64GcUnknownLinuxGnu => "riscv64-linux-gnu", + } + } + + pub const fn arch(&self) -> Arch { + use Arch::*; + use Target::*; + match *self { + X86_64UnknownLinuxGnu | X86_64AppleDarwin => X86_64, + AArch64UnknownLinuxGnu | AArch64AppleDarwin => AArch64, + I686UnknownLinuxGnu => X86, + ArmV7UnknownLinuxGnueabihf => Arm, + RiscV64GcUnknownLinuxGnu => RiscV64, + } + } + + pub const fn os(&self) -> Os { + use Os::*; + use Target::*; + match *self { + X86_64UnknownLinuxGnu + | AArch64UnknownLinuxGnu + | I686UnknownLinuxGnu + | ArmV7UnknownLinuxGnueabihf + | RiscV64GcUnknownLinuxGnu => Linux, + X86_64AppleDarwin | AArch64AppleDarwin => MacOs, + } + } +} + +impl Display for Target { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.rust_name()) + } +} + +impl Debug for Target { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.write_str(self.rust_name()) + } +} + +impl TryFrom<(Arch, Os)> for Target { + type Error = (); + + fn try_from((arch, os): (Arch, Os)) -> Result { + use Arch::*; + use Os::*; + use Target::*; + let target = match (arch, os) { + (X86_64, Linux) => X86_64UnknownLinuxGnu, + (X86_64, MacOs) => X86_64AppleDarwin, + (AArch64, Linux) => AArch64UnknownLinuxGnu, + (AArch64, MacOs) => AArch64AppleDarwin, + (X86, Linux) => I686UnknownLinuxGnu, + (Arm, Linux) => ArmV7UnknownLinuxGnueabihf, + (RiscV64, Linux) => RiscV64GcUnknownLinuxGnu, + (X86 | Arm | RiscV64, MacOs) => return Err(()), + }; + assert_eq!(target.arch(), arch); + assert_eq!(target.os(), os); + Ok(target) + } +} + +impl TryFrom<&str> for Target { + type Error = (); + + fn try_from(value: &str) -> Result { + for &target in Self::ALL { + if target.rust_name() == value { + return Ok(target); + } + } + Err(()) + } +} + +fn parse_cc1_commands(stderr: &str) -> Vec> { + stderr + .split('\n') + .filter_map(|line| { + let cc1 = "\"-cc1\""; + let i = line.find(cc1)?; + let args = &line[i..]; + let args = shell_words::split(args).unwrap(); + Some(args) + }) + .collect() +} + +fn cc1_command_to_driver_command(mut cc1_args: Vec) -> Vec { + let mut driver_args = Vec::new(); + + #[derive(PartialEq, Eq)] + enum Next { + Other, + ResourceDir, + ISystem, + Define, + } + + let mut next = Next::Other; + + for arg in cc1_args.drain(..) { + if next != Next::Other { + next = Next::Other; + driver_args.push(arg); + continue; + } + match arg.as_str() { + "-nostdsysteminc" => { + driver_args.push("-nostdinc".into()); + } + "-nobuiltininc" => { + driver_args.push(arg); + } + "-resource-dir" => { + next = Next::ResourceDir; + driver_args.push(arg); + } + "-isystem" => { + next = Next::ISystem; + driver_args.push(arg); + } + "-D" => { + next = Next::Define; + driver_args.push(arg); + } + _ => {} + } + } + + driver_args +} + +struct TargetArgs { + target: Target, + + /// `\0`-separated. + args: String, +} + +impl TargetArgs { + /// Use `zig cc` to determine the args needed to cross-compile to `target`. + /// `zig cc` is used because it can be otherwise quite difficult + /// to get the right headers for other OSes. + pub fn find(target: Target) -> Self { + let empty_c = NamedTempFile::new().unwrap(); + let empty_o = NamedTempFile::new().unwrap(); + let mut cmd = Command::new("zig"); + cmd.args([ + "cc", + "-target", + target.zig_name(), // + // `-###` will print the cc1 commands. + "-###", + // `-x c` is needed to tell `zig cc` this is a C file, since it isn't a `*.c`. + "-x", + "c", + // Don't use `-fsyntax-only`. `zig cc` doesn't handle it correctly. + // Don't use `-o /dev/null`. `zig cc` doesn't handle it correctly. "-c", "-o", - "/dev/null", - "-w", // Disable warnings. ]) - .arg(c_path) - .status(); - assert!(status.unwrap().success()); - - let (_temp_dir, temp_path) = - c2rust_transpile::create_temp_compile_commands(&[c_path.to_owned()]); - c2rust_transpile::transpile( - config(), - &temp_path, - &[ - "-w", // Disable warnings. - ], - ); - let cwd = current_dir().unwrap(); - let c_path = c_path.strip_prefix(&cwd).unwrap(); - // The crate name can't have `.`s in it, so use the file stem. - // This is also why we set it explicitly with `--crate-name`, - // as once we add `.{platform}`, the crate name derived from - // the file name won't be valid anymore. - let crate_name = c_path.file_stem().unwrap().to_str().unwrap(); - let rs_path = c_path.with_extension("rs"); - // We need to move the `.rs` file to a platform-specific name - // so that they don't overwrite each other. - let rs_path = match platform { - None => rs_path, - Some(platform) => { - let platform_rs_path = rs_path.with_extension(format!("{platform}.rs")); - fs::rename(&rs_path, &platform_rs_path).unwrap(); - platform_rs_path + .args([empty_o.path(), empty_c.path()]); + let output = cmd.output().unwrap(); + let stderr = from_utf8(&output.stderr).unwrap(); + if !output.status.success() { + eprintln!("> {cmd:?}"); + eprintln!("{stderr}") } - }; + assert!(output.status.success()); + let mut cc1_cmds = parse_cc1_commands(stderr); + // There should only be one cc1 command. + assert!(cc1_cmds.len() == 1); + let cc1_cmd = cc1_cmds.pop().unwrap(); + let driver_cmd = cc1_command_to_driver_command(cc1_cmd); + let args = driver_cmd.join("\0"); + Self { target, args } + } + + pub const fn target(&self) -> Target { + self.target + } - let edition = "2021"; + /// The `zig cc` args needed to cross-compile to [`Self::target`]. + pub const fn zig_cc_args(&self) -> [&str; 2] { + ["-target", self.target().zig_name()] + } - let status = Command::new("rustfmt") - .args(["--edition", edition]) - .arg(&rs_path) - .status(); - assert!(status.unwrap().success()); + pub fn clang_args_iter(&self) -> impl Iterator { + [ + "-target", + self.target.clang_name(), + // Undefine `__BLOCKS__` because `c2rust-ast-exporter` doesn't handle them at all. + // macOS headers use `__BLOCKS__` and `^` block pointers. + "-U", + "__BLOCKS__", + ] + .into_iter() + .chain(self.args.split('\0')) + } - let rs = fs::read_to_string(&rs_path).unwrap(); - let debug_expr = format!("cat {}", rs_path.display()); + /// The `clang` args needed to cross-compile to [`Self::target`]. + pub fn clang_args(&self) -> Vec<&str> { + self.clang_args_iter().collect() + } +} - let snapshot_name = match platform { - None => "transpile".into(), - Some(platform) => format!("transpile-{platform}"), - }; - insta::assert_snapshot!(snapshot_name, &rs, &debug_expr); - - // Using rustc itself to build snapshots that reference libc is difficult because we don't know - // the appropriate --extern libc=/path/to/liblibc-XXXXXXXXXXXXXXXX.rlib to pass. Skip for now, - // as we've already compared the literal text. - if rs.contains("libc::") { - eprintln!( - "warning: skipping compiling {} with rustc since it depends on libc", - rs_path.display() - ); - return; - } - - // Don't need to worry about platform clashes here, as this is immediately deleted. - let rlib_path = format!("lib{crate_name}.rlib"); - let status = Command::new("rustc") - .args([ - "+nightly-2023-04-15", - "--crate-type", - "lib", - "--edition", - edition, - "--crate-name", - crate_name, - "-o", - &rlib_path, - "-Awarnings", // Disable warnings. - ]) - .arg(&rs_path) - .status(); - assert!(status.unwrap().success()); - fs::remove_file(&rlib_path).unwrap(); +impl Display for TargetArgs { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + let args = self.clang_args_iter().join(" "); + write!(f, "{args}") + } +} + +struct Targets { + all: Vec, +} + +impl Targets { + pub fn find(targets: &[T]) -> Self + where + T: Copy, + Target: TryFrom, + >::Error: Debug, + { + let all = targets + .into_iter() + .copied() + .map(|target| Target::try_from(target).unwrap()) + .map(TargetArgs::find) + .collect(); + Self { all } + } + + pub fn get(&self, target: Target) -> &TargetArgs { + self.all + .iter() + .find(|args| args.target() == target) + .unwrap() + } +} + +impl Index for Targets { + type Output = TargetArgs; + + fn index(&self, index: Target) -> &Self::Output { + self.get(index) + } +} + +impl TargetArgs { + /// `platform` can be any platform-specific string. + /// It could be the `target_arch`, `target_os`, some combination, or something else. + pub fn transpile(&self, c_path: &Path, platform: &str) { + let cwd = current_dir().unwrap(); + let c_path = c_path.strip_prefix(&cwd).unwrap(); + // The crate name can't have `.`s in it, so use the file stem. + // This is also why we set it explicitly with `--crate-name`, + // as once we add `.{platform}`, the crate name derived from + // the file name won't be valid anymore. + let crate_name = c_path.file_stem().unwrap().to_str().unwrap(); + let original_rs_path = c_path.with_extension("rs"); + // We need to move the `.rs` file to a platform-specific name + // so that they don't overwrite each other. + let rs_path = match platform { + "" => original_rs_path.clone(), + _ => original_rs_path.with_extension(format!("{platform}.rs")), + }; + + { + let c_path = c_path.display(); + let rs_path = rs_path.display(); + let target = self.target().rust_name(); + println!("transpiling {c_path} to {rs_path} for --target {target}"); + } + + let o_path = NamedTempFile::new().unwrap(); + let status = Command::new("zig") + .arg("cc") + .args(self.zig_cc_args()) + .args([ + "-w", // Disable warnings. + "-c", "-o", // `zig cc` doesn't work with `-fsyntax-only` or `-o /dev/null`. + ]) + .args([o_path.path(), c_path]) + .status() + .unwrap(); + assert!(status.success()); + + let mut extra_args = self.clang_args(); + extra_args.push("-w"); // Disable warnings. + + let (_temp_dir, temp_path) = + c2rust_transpile::create_temp_compile_commands(&[c_path.to_owned()]); + c2rust_transpile::transpile(config(), &temp_path, &extra_args); + + if !platform.is_empty() { + fs::rename(&original_rs_path, &rs_path).unwrap(); + } + + let edition = "2021"; + + let status = Command::new("rustfmt") + .args(["--edition", edition]) + .arg(&rs_path) + .status(); + assert!(status.unwrap().success()); + + let rs = fs::read_to_string(&rs_path).unwrap(); + let debug_expr = format!("cat {}", rs_path.display()); + + let snapshot_name = match platform { + "" => "transpile".into(), + _ => format!("transpile-{platform}"), + }; + insta::assert_snapshot!(snapshot_name, &rs, &debug_expr); + + // Using rustc itself to build snapshots that reference libc is difficult because we don't know + // the appropriate --extern libc=/path/to/liblibc-XXXXXXXXXXXXXXXX.rlib to pass. Skip for now, + // as we've already compared the literal text. + if rs.contains("libc::") { + eprintln!( + "warning: skipping compiling {} with rustc since it depends on libc", + rs_path.display() + ); + return; + } + + // Don't need to worry about platform clashes here, as this is immediately deleted. + let rlib_path = format!("lib{crate_name}.rlib"); + let status = Command::new("rustc") + .args([ + &format!("+{GENERATED_RUST_TOOLCHAIN}"), + "--crate-type", + "lib", + "--edition", + edition, + "--target", + self.target().rust_name(), + "--crate-name", + crate_name, + "-o", + &rlib_path, + "-Awarnings", // Disable warnings. + ]) + .arg(&rs_path) + .status(); + assert!(status.unwrap().success()); + fs::remove_file(&rlib_path).unwrap(); + } +} + +impl Targets { + pub fn check_if_targets_are_installed(&self) { + let output = Command::new("rustup") + .args([ + &format!("+{GENERATED_RUST_TOOLCHAIN}"), + "target", + "list", + "--installed", + ]) + .output() + .unwrap(); + assert!(output.status.success()); + let installed_targets = from_utf8(&output.stdout) + .unwrap() + .trim() + .split_whitespace() + .collect::>(); + let uninstalled_targets = self + .all + .iter() + .map(|args| args.target().rust_name()) + .filter(|target| !installed_targets.contains(target)) + .join(" "); + if !uninstalled_targets.is_empty() { + panic!("not all targets installed, run:\nrustup +{GENERATED_RUST_TOOLCHAIN} target add {uninstalled_targets}\n"); + } + } + + pub fn transpile<'a, P>(&self, c_path: &Path, get_platform: impl Fn(Target) -> P) + where + P: Into>, + { + let mut platforms = HashMap::, Vec<&TargetArgs>>::new(); + for target in self.all.iter() { + let platform = get_platform(target.target()); + platforms.entry(platform.into()).or_default().push(target); + } + for (platform, targets) in platforms { + for target_args in targets { + target_args.transpile(c_path, &platform); + } + } + } } #[test] fn transpile_all() { - insta::glob!("snapshots/*.c", |x| transpile(None, x)); - - // Some things transpile differently on Linux vs. macOS, - // as they use `unsigned long` and `unsigned long long` differently for builtins. - // This makes snapshot tests trickier, as the output will be OS-dependent. - // We handle this by adding OS name to the snapshot result filename. - #[allow(unused)] - let os = "unknown"; - - #[cfg(target_os = "linux")] - let os = "linux"; - #[cfg(target_os = "macos")] - let os = "macos"; - - // Similarly, some things transpile differently on different architectures. - #[allow(unused)] - let arch = "unknown"; - - #[cfg(target_arch = "x86")] - let arch = "x86"; - #[cfg(target_arch = "x86_64")] - let arch = "x86_64"; - #[cfg(target_arch = "arm")] - let arch = "arm"; - #[cfg(target_arch = "aarch64")] - let arch = "aarch64"; - - insta::with_settings!({snapshot_suffix => os}, { - insta::glob!("snapshots/os-specific/*.c", |path| transpile(Some(os), path)); - }); - - insta::with_settings!({snapshot_suffix => arch}, { - insta::glob!("snapshots/arch-specific/*.c", |path| transpile(Some(arch), path)); - }) + let targets = Targets::find(&[ + "x86_64-unknown-linux-gnu", + "x86_64-apple-darwin", + "aarch64-unknown-linux-gnu", + "aarch64-apple-darwin", + "i686-unknown-linux-gnu", + "armv7-unknown-linux-gnueabihf", + ]); + targets.check_if_targets_are_installed(); + + let transpile = |path: &Path| { + let dir = path.parent().unwrap(); + let dir_name = dir.file_name().unwrap_or_default(); + let dir_name = dir_name.to_str().unwrap_or_default(); + match dir_name { + "snapshots" => targets.transpile(path, |_| ""), + "os-specific" => targets.transpile(path, |target| target.os().name()), + "arch-specific" => targets.transpile(path, |target| target.arch().name()), + "ptr-width-specific" => { + targets.transpile(path, |target| format!("{}", target.arch().ptr_width())) + } + "os-ptr-width-specific" => targets.transpile(path, |target| { + format!("{}-{}", target.os(), target.arch().ptr_width()) + }), + _ => unreachable!(), + } + }; + + insta::glob!("snapshots/**/*.c", transpile); } diff --git a/c2rust-transpile/tests/snapshots/arch-specific/dummy.c b/c2rust-transpile/tests/snapshots/arch-specific/dummy.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c b/c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c index d5807dcf13..da87436634 100644 --- a/c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c +++ b/c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c @@ -76,12 +76,15 @@ int VM_CallCompiled(vm_t *vm, int *args) : "cc", "memory", "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11" ); #elif __i386__ - __asm__ volatile( - "calll *%3\n" - : "+S" (programStack), "+D" (opStack), "+b" (opStackOfs) - : "g" (entryPoint) - : "cc", "memory", "%eax", "%ecx", "%edx" - ); + // TODO transpilation is broken: + // `unknown use of instruction mnemonic without a size suffix` on the `mov`. + + // __asm__ volatile( + // "calll *%3\n" + // : "+S" (programStack), "+D" (opStack), "+b" (opStackOfs) + // : "g" (entryPoint) + // : "cc", "memory", "%eax", "%ecx", "%edx" + // ); #endif if(opStackOfs != 1 || *opStack != 0xDEADBEEF) diff --git a/c2rust-transpile/tests/snapshots/macros.c b/c2rust-transpile/tests/snapshots/macros.c index ec07af1bb8..e38d845c98 100644 --- a/c2rust-transpile/tests/snapshots/macros.c +++ b/c2rust-transpile/tests/snapshots/macros.c @@ -1,6 +1,5 @@ #include #include -#include struct S { int i; @@ -385,8 +384,6 @@ int local_fn(void) { return 1234; } int use_local_value(void) { return LOCAL_VALUE; } -bool use_portable_type(uintptr_t len) { return len <= UINTPTR_MAX / 2; } - // From `curl`'s `curl_ntlm_core.c`. struct ntlmdata { diff --git a/c2rust-transpile/tests/snapshots/os-specific/rotate.c b/c2rust-transpile/tests/snapshots/os-ptr-width-specific/rotate.c similarity index 100% rename from c2rust-transpile/tests/snapshots/os-specific/rotate.c rename to c2rust-transpile/tests/snapshots/os-ptr-width-specific/rotate.c diff --git a/c2rust-transpile/tests/snapshots/ptr-width-specific/macros.c b/c2rust-transpile/tests/snapshots/ptr-width-specific/macros.c new file mode 100644 index 0000000000..e5d498b134 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/ptr-width-specific/macros.c @@ -0,0 +1,4 @@ +#include +#include + +bool use_portable_type(uintptr_t len) { return len <= UINTPTR_MAX / 2; } diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-32@ptr-width-specific__macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-32@ptr-width-specific__macros.c.snap new file mode 100644 index 0000000000..245c6e7262 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-32@ptr-width-specific__macros.c.snap @@ -0,0 +1,19 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/ptr-width-specific/macros.32.rs +input_file: c2rust-transpile/tests/snapshots/ptr-width-specific/macros.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +pub type uintptr_t = usize; +pub const UINTPTR_MAX: ::core::ffi::c_uint = 4294967295 as ::core::ffi::c_uint; +#[no_mangle] +pub unsafe extern "C" fn use_portable_type(mut len: uintptr_t) -> bool { + return len <= (UINTPTR_MAX as uintptr_t).wrapping_div(2 as uintptr_t); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-64@ptr-width-specific__macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-64@ptr-width-specific__macros.c.snap new file mode 100644 index 0000000000..a529d65e41 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-64@ptr-width-specific__macros.c.snap @@ -0,0 +1,19 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/ptr-width-specific/macros.64.rs +input_file: c2rust-transpile/tests/snapshots/ptr-width-specific/macros.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +pub type uintptr_t = usize; +pub const UINTPTR_MAX: ::core::ffi::c_ulong = 18446744073709551615 as ::core::ffi::c_ulong; +#[no_mangle] +pub unsafe extern "C" fn use_portable_type(mut len: uintptr_t) -> bool { + return len <= (UINTPTR_MAX as uintptr_t).wrapping_div(2 as uintptr_t); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@spin.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@arch-specific__spin.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@spin.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@arch-specific__spin.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@arch-specific__vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@arch-specific__vm_x86.c.snap new file mode 100644 index 0000000000..cd0b7aced0 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@arch-specific__vm_x86.c.snap @@ -0,0 +1,71 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/vm_x86.aarch64.rs +input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#[derive(Copy, Clone)] +#[repr(C)] +pub struct vm_t { + pub programStack: ::core::ffi::c_int, + pub entryOfs: ::core::ffi::c_int, + pub dataBase: *mut ::core::ffi::c_void, + pub codeBase: *mut ::core::ffi::c_void, + pub instructionPointers: *mut ::core::ffi::c_ulong, +} +pub type byte = ::core::ffi::c_uchar; +pub const MAX_VMMAIN_ARGS: ::core::ffi::c_int = 50 as ::core::ffi::c_int; +#[no_mangle] +pub unsafe extern "C" fn VM_CallCompiled( + mut vm: *mut vm_t, + mut args: *mut ::core::ffi::c_int, +) -> ::core::ffi::c_int { + let mut stack: [byte; 271] = [0; 271]; + let mut entryPoint: *mut ::core::ffi::c_void = 0 as *mut ::core::ffi::c_void; + let mut programStack: ::core::ffi::c_int = 0; + let mut stackOnEntry: ::core::ffi::c_int = 0; + let mut image: *mut byte = 0 as *mut byte; + let mut opStack: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int; + let mut opStackOfs: ::core::ffi::c_int = 0; + let mut arg: ::core::ffi::c_int = 0; + let mut currentVM: *mut vm_t = vm; + stackOnEntry = (*vm).programStack; + programStack = stackOnEntry; + image = (*vm).dataBase as *mut byte; + programStack -= 8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS; + arg = 0 as ::core::ffi::c_int; + while arg < MAX_VMMAIN_ARGS { + *(&mut *image.offset( + (programStack + 8 as ::core::ffi::c_int + arg * 4 as ::core::ffi::c_int) as isize, + ) as *mut byte as *mut ::core::ffi::c_int) = *args.offset(arg as isize); + arg += 1; + } + *(&mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut byte + as *mut ::core::ffi::c_int) = 0 as ::core::ffi::c_int; + *(&mut *image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = + -(1 as ::core::ffi::c_int); + entryPoint = ((*vm).codeBase).offset((*vm).entryOfs as isize); + opStack = + (stack.as_mut_ptr() as *mut ::core::ffi::c_int).offset(16 as ::core::ffi::c_int as isize); + *opStack = 0 as ::core::ffi::c_int; + opStackOfs = 0 as ::core::ffi::c_int; + if opStackOfs != 1 as ::core::ffi::c_int + || *opStack as ::core::ffi::c_uint != 0xdeadbeef as ::core::ffi::c_uint + { + return 0 as ::core::ffi::c_int; + } + if programStack + != stackOnEntry - (8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS) + { + return 0 as ::core::ffi::c_int; + } + (*vm).programStack = stackOnEntry; + return *opStack.offset(opStackOfs as isize); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@dummy.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@dummy.c.snap deleted file mode 100644 index d8beb1e9af..0000000000 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@dummy.c.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/arch-specific/dummy.aarch64.rs -input_file: c2rust-transpile/tests/snapshots/arch-specific/dummy.c ---- -#![allow( - dead_code, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_assignments, - unused_mut -)] diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__spin.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__spin.c.snap new file mode 100644 index 0000000000..35287d6f8d --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__spin.c.snap @@ -0,0 +1,22 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/spin.arm.rs +input_file: c2rust-transpile/tests/snapshots/arch-specific/spin.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![feature(stdsimd)] +#[cfg(target_arch = "aarch64")] +pub use ::core::arch::aarch64::__yield; +#[cfg(target_arch = "arm")] +pub use ::core::arch::arm::__yield; +#[no_mangle] +pub unsafe extern "C" fn spin() { + __yield(); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__vm_x86.c.snap similarity index 97% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__vm_x86.c.snap index 62be750e16..e063f4ec6d 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-aarch64@vm_x86.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-arm@arch-specific__vm_x86.c.snap @@ -1,6 +1,6 @@ --- source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/arch-specific/vm_x86.x86_64.rs +expression: cat tests/snapshots/arch-specific/vm_x86.arm.rs input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c --- #![allow( diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@rotate.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux-32@os-ptr-width-specific__rotate.c.snap similarity index 80% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-macos@rotate.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux-32@os-ptr-width-specific__rotate.c.snap index f6e1255ff6..55655d82d9 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@rotate.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux-32@os-ptr-width-specific__rotate.c.snap @@ -1,7 +1,7 @@ --- source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/os-specific/rotate.macos.rs -input_file: c2rust-transpile/tests/snapshots/os-specific/rotate.c +expression: cat tests/snapshots/os-ptr-width-specific/rotate.linux-32.rs +input_file: c2rust-transpile/tests/snapshots/os-ptr-width-specific/rotate.c --- #![allow( dead_code, diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@rotate.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux-64@os-ptr-width-specific__rotate.c.snap similarity index 83% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-linux@rotate.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux-64@os-ptr-width-specific__rotate.c.snap index 5db0995d02..e228215f26 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@rotate.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux-64@os-ptr-width-specific__rotate.c.snap @@ -1,7 +1,7 @@ --- source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/os-specific/rotate.linux.rs -input_file: c2rust-transpile/tests/snapshots/os-specific/rotate.c +expression: cat tests/snapshots/os-ptr-width-specific/rotate.linux-64.rs +input_file: c2rust-transpile/tests/snapshots/os-ptr-width-specific/rotate.c --- #![allow( dead_code, diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__macros.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-linux@macros.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__macros.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@rnd.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__rnd.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-linux@rnd.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__rnd.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@sigign.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__sigign.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-linux@sigign.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__sigign.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@types.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__types.c.snap similarity index 92% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-linux@types.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__types.c.snap index 5e14aeac65..e3b40f4150 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@types.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-linux@os-specific__types.c.snap @@ -1,8 +1,7 @@ --- source: c2rust-transpile/tests/snapshots.rs -assertion_line: 69 -expression: cat tests/snapshots/platform-specific/types.rs -input_file: c2rust-transpile/tests/snapshots/platform-specific/types.c +expression: cat tests/snapshots/os-specific/types.linux.rs +input_file: c2rust-transpile/tests/snapshots/os-specific/types.c --- #![allow( dead_code, @@ -67,4 +66,3 @@ pub static mut int64var: int64_t = 0 as int64_t; pub static mut maxvar: intmax_t = 0 as intmax_t; #[no_mangle] pub static mut umaxvar: uintmax_t = 0 as uintmax_t; - diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos-64@os-ptr-width-specific__rotate.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos-64@os-ptr-width-specific__rotate.c.snap new file mode 100644 index 0000000000..916a6acb01 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos-64@os-ptr-width-specific__rotate.c.snap @@ -0,0 +1,25 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/os-ptr-width-specific/rotate.macos-64.rs +input_file: c2rust-transpile/tests/snapshots/os-ptr-width-specific/rotate.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#[no_mangle] +pub unsafe extern "C" fn rotate_left_64( + mut x: ::core::ffi::c_ulonglong, +) -> ::core::ffi::c_ulonglong { + return x.rotate_left(4 as ::core::ffi::c_int as ::core::ffi::c_ulonglong as u32); +} +#[no_mangle] +pub unsafe extern "C" fn rotate_right_64( + mut x: ::core::ffi::c_ulonglong, +) -> ::core::ffi::c_ulonglong { + return x.rotate_right(4 as ::core::ffi::c_int as ::core::ffi::c_ulonglong as u32); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__macros.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-macos@macros.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__macros.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@rnd.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__rnd.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-macos@rnd.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__rnd.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@sigign.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__sigign.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-macos@sigign.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__sigign.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@types.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__types.c.snap similarity index 88% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-macos@types.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__types.c.snap index 7f4315b098..a672d87a22 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@types.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-macos@os-specific__types.c.snap @@ -1,8 +1,7 @@ --- source: c2rust-transpile/tests/snapshots.rs -assertion_line: 69 -expression: cat tests/snapshots/platform-specific/types.rs -input_file: c2rust-transpile/tests/snapshots/platform-specific/types.c +expression: cat tests/snapshots/os-specific/types.macos.rs +input_file: c2rust-transpile/tests/snapshots/os-specific/types.c --- #![allow( dead_code, @@ -12,7 +11,6 @@ input_file: c2rust-transpile/tests/snapshots/platform-specific/types.c unused_assignments, unused_mut )] -pub type __darwin_ptrdiff_t = isize; pub type __darwin_size_t = usize; pub type __darwin_ssize_t = isize; pub type int8_t = i8; @@ -28,7 +26,7 @@ pub type uint32_t = u32; pub type uint64_t = u64; pub type intmax_t = ::libc::intmax_t; pub type uintmax_t = ::libc::uintmax_t; -pub type ptrdiff_t = __darwin_ptrdiff_t; +pub type ptrdiff_t = isize; pub type ssize_t = __darwin_ssize_t; #[no_mangle] pub static mut intvar: ::core::ffi::c_int = 0 as ::core::ffi::c_int; @@ -62,4 +60,3 @@ pub static mut int64var: int64_t = 0 as int64_t; pub static mut maxvar: intmax_t = 0 as intmax_t; #[no_mangle] pub static mut umaxvar: uintmax_t = 0 as uintmax_t; - diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__spin.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__spin.c.snap new file mode 100644 index 0000000000..e939a878e4 --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__spin.c.snap @@ -0,0 +1,22 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/spin.x86.rs +input_file: c2rust-transpile/tests/snapshots/arch-specific/spin.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#![feature(stdsimd)] +#[cfg(target_arch = "x86")] +pub use ::core::arch::x86::_mm_pause; +#[cfg(target_arch = "x86_64")] +pub use ::core::arch::x86_64::_mm_pause; +#[no_mangle] +pub unsafe extern "C" fn spin() { + _mm_pause(); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__vm_x86.c.snap new file mode 100644 index 0000000000..e92154088e --- /dev/null +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86@arch-specific__vm_x86.c.snap @@ -0,0 +1,71 @@ +--- +source: c2rust-transpile/tests/snapshots.rs +expression: cat tests/snapshots/arch-specific/vm_x86.x86.rs +input_file: c2rust-transpile/tests/snapshots/arch-specific/vm_x86.c +--- +#![allow( + dead_code, + non_camel_case_types, + non_snake_case, + non_upper_case_globals, + unused_assignments, + unused_mut +)] +#[derive(Copy, Clone)] +#[repr(C)] +pub struct vm_t { + pub programStack: ::core::ffi::c_int, + pub entryOfs: ::core::ffi::c_int, + pub dataBase: *mut ::core::ffi::c_void, + pub codeBase: *mut ::core::ffi::c_void, + pub instructionPointers: *mut ::core::ffi::c_ulong, +} +pub type byte = ::core::ffi::c_uchar; +pub const MAX_VMMAIN_ARGS: ::core::ffi::c_int = 50 as ::core::ffi::c_int; +#[no_mangle] +pub unsafe extern "C" fn VM_CallCompiled( + mut vm: *mut vm_t, + mut args: *mut ::core::ffi::c_int, +) -> ::core::ffi::c_int { + let mut stack: [byte; 271] = [0; 271]; + let mut entryPoint: *mut ::core::ffi::c_void = 0 as *mut ::core::ffi::c_void; + let mut programStack: ::core::ffi::c_int = 0; + let mut stackOnEntry: ::core::ffi::c_int = 0; + let mut image: *mut byte = 0 as *mut byte; + let mut opStack: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int; + let mut opStackOfs: ::core::ffi::c_int = 0; + let mut arg: ::core::ffi::c_int = 0; + let mut currentVM: *mut vm_t = vm; + stackOnEntry = (*vm).programStack; + programStack = stackOnEntry; + image = (*vm).dataBase as *mut byte; + programStack -= 8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS; + arg = 0 as ::core::ffi::c_int; + while arg < MAX_VMMAIN_ARGS { + *(&mut *image.offset( + (programStack + 8 as ::core::ffi::c_int + arg * 4 as ::core::ffi::c_int) as isize, + ) as *mut byte as *mut ::core::ffi::c_int) = *args.offset(arg as isize); + arg += 1; + } + *(&mut *image.offset((programStack + 4 as ::core::ffi::c_int) as isize) as *mut byte + as *mut ::core::ffi::c_int) = 0 as ::core::ffi::c_int; + *(&mut *image.offset(programStack as isize) as *mut byte as *mut ::core::ffi::c_int) = + -(1 as ::core::ffi::c_int); + entryPoint = ((*vm).codeBase).offset((*vm).entryOfs as isize); + opStack = + (stack.as_mut_ptr() as *mut ::core::ffi::c_int).offset(16 as ::core::ffi::c_int as isize); + *opStack = 0 as ::core::ffi::c_int; + opStackOfs = 0 as ::core::ffi::c_int; + if opStackOfs != 1 as ::core::ffi::c_int + || *opStack as ::core::ffi::c_uint != 0xdeadbeef as ::core::ffi::c_uint + { + return 0 as ::core::ffi::c_int; + } + if programStack + != stackOnEntry - (8 as ::core::ffi::c_int + 4 as ::core::ffi::c_int * MAX_VMMAIN_ARGS) + { + return 0 as ::core::ffi::c_int; + } + (*vm).programStack = stackOnEntry; + return *opStack.offset(opStackOfs as isize); +} diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@spin.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@arch-specific__spin.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@spin.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@arch-specific__spin.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@arch-specific__vm_x86.c.snap similarity index 100% rename from c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@vm_x86.c.snap rename to c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@arch-specific__vm_x86.c.snap diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@dummy.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@dummy.c.snap deleted file mode 100644 index c23accc4da..0000000000 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile-x86_64@dummy.c.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: c2rust-transpile/tests/snapshots.rs -expression: cat tests/snapshots/arch-specific/dummy.x86_64.rs -input_file: c2rust-transpile/tests/snapshots/arch-specific/dummy.c ---- -#![allow( - dead_code, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unused_assignments, - unused_mut -)] diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@incomplete_arrays.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@incomplete_arrays.c.snap index 4a422a89f3..622c36cb42 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@incomplete_arrays.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@incomplete_arrays.c.snap @@ -1,6 +1,5 @@ --- source: c2rust-transpile/tests/snapshots.rs -assertion_line: 80 expression: cat tests/snapshots/incomplete_arrays.rs input_file: c2rust-transpile/tests/snapshots/incomplete_arrays.c --- @@ -12,4 +11,3 @@ input_file: c2rust-transpile/tests/snapshots/incomplete_arrays.c unused_assignments, unused_mut )] - diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap index 4de2fbc9b4..771fef1ce3 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap @@ -14,7 +14,6 @@ input_file: c2rust-transpile/tests/snapshots/macros.c extern "C" { fn extern_fn() -> ::core::ffi::c_int; } -pub type uintptr_t = usize; #[derive(Copy, Clone)] #[repr(C)] pub struct S { @@ -35,7 +34,6 @@ pub struct ntlmdata { pub target_info_len: ::core::ffi::c_uint, } pub const true_0: ::core::ffi::c_int = 1 as ::core::ffi::c_int; -pub const UINTPTR_MAX: ::core::ffi::c_ulong = 18446744073709551615 as ::core::ffi::c_ulong; pub const LITERAL_INT: ::core::ffi::c_int = 0xffff as ::core::ffi::c_int; pub const LITERAL_BOOL: ::core::ffi::c_int = true_0; pub const LITERAL_FLOAT: ::core::ffi::c_double = 3.14f64; @@ -426,10 +424,6 @@ pub unsafe extern "C" fn use_local_value() -> ::core::ffi::c_int { return local_fn(); } #[no_mangle] -pub unsafe extern "C" fn use_portable_type(mut len: uintptr_t) -> bool { - return len <= (UINTPTR_MAX as uintptr_t).wrapping_div(2 as uintptr_t); -} -#[no_mangle] pub unsafe extern "C" fn ntlm_v2_blob_len(mut ntlm: *mut ntlmdata) -> ::core::ffi::c_uint { return ((44 as ::core::ffi::c_int - 16 as ::core::ffi::c_int) as ::core::ffi::c_uint) .wrapping_add((*ntlm).target_info_len)