diff --git a/cli/src/build.rs b/cli/src/build.rs index e5c44aceee..b9ae821652 100644 --- a/cli/src/build.rs +++ b/cli/src/build.rs @@ -79,6 +79,7 @@ pub fn build_file<'a>( Architecture::X86_64 => false, Architecture::Aarch64(_) => false, Architecture::Wasm32 => true, + Architecture::X86_32(_) => false, _ => panic!( "TODO gracefully handle unsupported architecture: {:?}", target.architecture diff --git a/cli/src/lib.rs b/cli/src/lib.rs index d7f1774c37..8c6be1921c 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -16,7 +16,7 @@ use std::path::{Path, PathBuf}; use std::process; use std::process::Command; use target_lexicon::BinaryFormat; -use target_lexicon::{Architecture, Triple}; +use target_lexicon::{Architecture, Triple, X86_32Architecture}; pub mod build; pub mod repl; @@ -58,8 +58,8 @@ pub fn build_app<'a>() -> App<'a> { .long(FLAG_BACKEND) .help("Choose a different backend") // .requires(BACKEND) - .default_value("llvm") - .possible_values(&["llvm", "wasm", "asm"]) + .default_value(Backend::default().as_str()) + .possible_values(Backend::OPTIONS) .required(false), ) .arg( @@ -135,8 +135,8 @@ pub fn build_app<'a>() -> App<'a> { .long(FLAG_BACKEND) .help("Choose a different backend") // .requires(BACKEND) - .default_value("llvm") - .possible_values(&["llvm", "wasm", "asm"]) + .default_value(Backend::default().as_str()) + .possible_values(Backend::OPTIONS) .required(false), ) .arg( @@ -180,25 +180,19 @@ pub enum BuildConfig { BuildAndRun { roc_file_arg_index: usize }, } -fn wasm32_target_tripple() -> Triple { - let mut triple = Triple::unknown(); - - triple.architecture = Architecture::Wasm32; - triple.binary_format = BinaryFormat::Wasm; - - triple -} - #[cfg(feature = "llvm")] pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result { use build::build_file; + use std::str::FromStr; use BuildConfig::*; - let target = match matches.value_of(FLAG_BACKEND) { - Some("wasm") => wasm32_target_tripple(), - _ => Triple::host(), + let backend = match matches.value_of(FLAG_BACKEND) { + Some(name) => Backend::from_str(name).unwrap(), + None => Backend::default(), }; + let target = backend.to_triple(); + let arena = Bump::new(); let filename = matches.value_of(ROC_FILE).unwrap(); @@ -387,3 +381,90 @@ fn run_with_wasmer(wasm_path: &std::path::Path, args: &[String]) { start.call(&[]).unwrap(); } + +enum Backend { + Host, + X86_32, + X86_64, + Dev, + Wasm32, + Wasm32Dev, +} + +impl Default for Backend { + fn default() -> Self { + Backend::Host + } +} + +impl Backend { + const fn as_str(&self) -> &'static str { + match self { + Backend::Host => "host", + Backend::X86_32 => "x86_32", + Backend::X86_64 => "x86_64", + Backend::Dev => "dev", + Backend::Wasm32 => "wasm32", + Backend::Wasm32Dev => "wasm32_dev", + } + } + + /// NOTE keep up to date! + const OPTIONS: &'static [&'static str] = &[ + Backend::Host.as_str(), + Backend::X86_32.as_str(), + Backend::X86_64.as_str(), + Backend::Dev.as_str(), + Backend::Wasm32.as_str(), + Backend::Wasm32Dev.as_str(), + ]; + + fn to_triple(&self) -> Triple { + let mut triple = Triple::unknown(); + + match self { + Backend::Host => Triple::host(), + Backend::X86_32 => { + triple.architecture = Architecture::X86_32(X86_32Architecture::I386); + triple.binary_format = BinaryFormat::Elf; + + triple + } + Backend::X86_64 => { + triple.architecture = Architecture::X86_64; + triple.binary_format = BinaryFormat::Elf; + + triple + } + Backend::Dev => todo!(), + Backend::Wasm32 | Backend::Wasm32Dev => { + triple.architecture = Architecture::Wasm32; + triple.binary_format = BinaryFormat::Wasm; + + triple + } + } + } +} + +impl std::fmt::Display for Backend { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl std::str::FromStr for Backend { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "host" => Ok(Backend::Host), + "x86_32" => Ok(Backend::X86_32), + "x86_64" => Ok(Backend::X86_64), + "dev" => Ok(Backend::Dev), + "wasm32" => Ok(Backend::Wasm32), + "wasm32_dev" => Ok(Backend::Wasm32Dev), + _ => Err(()), + } + } +} diff --git a/compiler/build/src/link.rs b/compiler/build/src/link.rs index 7d55f7e6c6..d83174d015 100644 --- a/compiler/build/src/link.rs +++ b/compiler/build/src/link.rs @@ -248,6 +248,16 @@ pub fn rebuild_host(target: &Triple, host_input_path: &Path) { zig_str_path.to_str().unwrap(), ) } + Architecture::X86_32(_) => { + let emit_bin = format!("-femit-bin={}", host_dest_native.to_str().unwrap()); + build_zig_host_native( + &env_path, + &env_home, + &emit_bin, + zig_host_src.to_str().unwrap(), + zig_str_path.to_str().unwrap(), + ) + } _ => panic!("Unsupported architecture {:?}", target.architecture), }; @@ -396,6 +406,8 @@ fn link_linux( let ld_linux = match target.architecture { Architecture::X86_64 => library_path(["/lib64", "ld-linux-x86-64.so.2"]) .or_else(|| library_path([&nixos_path(), "ld-linux-x86-64.so.2"])), + Architecture::X86_32(_) => library_path(["/lib32", "ld-linux.so.2"]) + .or_else(|| library_path([&nixos_path(), "ld-linux.so.2"])), Architecture::Aarch64(_) => library_path(["/lib", "ld-linux-aarch64.so.1"]), _ => panic!( "TODO gracefully handle unsupported linux architecture: {:?}", diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index 9bb9f5464e..b3a6ec2d7a 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -221,7 +221,7 @@ pub fn gen_from_mono_module( use target_lexicon::Architecture; match target.architecture { - Architecture::X86_64 | Architecture::Aarch64(_) => { + Architecture::X86_64 | Architecture::X86_32(_) | Architecture::Aarch64(_) => { // assemble the .ll into a .bc let _ = Command::new("llvm-as") .args(&[