diff --git a/Cargo.lock b/Cargo.lock index 7cd42c78d6..b893442f99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3168,6 +3168,7 @@ dependencies = [ name = "roc_target" version = "0.0.1" dependencies = [ + "roc_error_macros", "strum", "strum_macros", "target-lexicon", diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index eaea5ce76d..978f42d460 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -23,7 +23,7 @@ use roc_mono::ir::OptLevel; use roc_packaging::cache::RocCacheDir; use roc_packaging::tarball::Compression; use roc_reporting::report::ANSI_STYLE_CODES; -use roc_target::Target; +use roc_target::{Architecture, Target}; use std::env; use std::ffi::{CString, OsStr, OsString}; use std::io; @@ -33,7 +33,6 @@ use std::path::{Path, PathBuf}; use std::process; use std::time::{Duration, Instant}; use strum::IntoEnumIterator; -use target_lexicon::{Architecture, Triple}; #[cfg(not(target_os = "linux"))] use tempfile::TempDir; @@ -442,7 +441,7 @@ fn opt_level_from_flags(matches: &ArgMatches) -> OptLevel { } #[cfg(windows)] -pub fn test(_matches: &ArgMatches, _triple: Triple) -> io::Result { +pub fn test(_matches: &ArgMatches, _target: Target) -> io::Result { todo!("running tests does not work on windows right now") } @@ -454,11 +453,10 @@ struct ModuleTestResults { } #[cfg(not(windows))] -pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result { +pub fn test(matches: &ArgMatches, target: Target) -> io::Result { use roc_build::program::report_problems_monomorphized; use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError}; use roc_packaging::cache; - use roc_target::TargetInfo; let start_time = Instant::now(); let arena = Bump::new(); @@ -495,14 +493,12 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result { } let arena = &arena; - let target = &triple; - let target_info = TargetInfo::from(target); // TODO may need to determine this dynamically based on dev builds. let function_kind = FunctionKind::LambdaSet; // Step 1: compile the app and generate the .o file let load_config = LoadConfig { - target_info, + target, function_kind, // TODO: expose this from CLI? render: roc_reporting::report::RenderTarget::ColorTerminal, @@ -536,7 +532,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result { let (dyn_lib, expects_by_module, layout_interner) = roc_repl_expect::run::expect_mono_module_to_dylib( arena, - target.clone(), + target, loaded, opt_level, LlvmBackendMode::CliTest, @@ -673,7 +669,7 @@ pub fn build( matches: &ArgMatches, subcommands: &[String], config: BuildConfig, - triple: Triple, + target: Target, out_path: Option<&Path>, roc_cache_dir: RocCacheDir<'_>, link_type: LinkType, @@ -784,7 +780,7 @@ pub fn build( // Note: This allows using `--dev` with `--optimize`. // This means frontend optimizations and dev backend. let code_gen_backend = if matches.get_flag(FLAG_DEV) { - if matches!(triple.architecture, Architecture::Wasm32) { + if matches!(target.architecture(), Architecture::Wasm32) { CodeGenBackend::Wasm } else { CodeGenBackend::Assembly(AssemblyBackendMode::Binary) @@ -818,7 +814,7 @@ pub fn build( let linking_strategy = if wasm_dev_backend { LinkingStrategy::Additive - } else if !roc_linker::supported(link_type, &triple) + } else if !roc_linker::supported(link_type, target) || matches.get_one::(FLAG_LINKER).map(|s| s.as_str()) == Some("legacy") { LinkingStrategy::Legacy @@ -827,8 +823,8 @@ pub fn build( }; let prebuilt = { - let cross_compile = triple != Triple::host(); - let targeting_wasm = matches!(triple.architecture, Architecture::Wasm32); + let cross_compile = target != Target::default(); + let targeting_wasm = matches!(target.architecture(), Architecture::Wasm32); matches.get_flag(FLAG_PREBUILT) || // When compiling for a different target, assume a prebuilt platform. @@ -862,11 +858,11 @@ pub fn build( fuzz, }; - let load_config = standard_load_config(&triple, build_ordering, threading); + let load_config = standard_load_config(target, build_ordering, threading); let res_binary_path = build_file( &arena, - &triple, + target, path.to_owned(), code_gen_options, emit_timings, @@ -933,7 +929,7 @@ pub fn build( // ManuallyDrop will leak the bytes because we don't drop manually let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap()); - roc_run(&arena, opt_level, triple, args, bytes, expect_metadata) + roc_run(&arena, opt_level, target, args, bytes, expect_metadata) } BuildAndRunIfNoErrors => { if problems.fatally_errored { @@ -968,7 +964,7 @@ pub fn build( // ManuallyDrop will leak the bytes because we don't drop manually let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap()); - roc_run(&arena, opt_level, triple, args, bytes, expect_metadata) + roc_run(&arena, opt_level, target, args, bytes, expect_metadata) } } } @@ -982,12 +978,12 @@ pub fn build( fn roc_run<'a, I: IntoIterator>( arena: &Bump, opt_level: OptLevel, - triple: Triple, + target: Target, args: I, binary_bytes: &[u8], expect_metadata: ExpectMetadata, ) -> io::Result { - match triple.architecture { + match target.architecture() { Architecture::Wasm32 => { let executable = roc_run_executable_file_path(binary_bytes)?; let path = executable.as_path(); diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index e2b5751923..06e101fa7f 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -15,7 +15,7 @@ use roc_gen_dev::AssemblyBackendMode; use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_load::{FunctionKind, LoadingProblem, Threading}; use roc_packaging::cache::{self, RocCacheDir}; -use roc_target::{get_target_triple_str, Target}; +use roc_target::Target; use std::fs::{self, FileType}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; @@ -49,7 +49,7 @@ fn main() -> io::Result<()> { &matches, &subcommands, BuildConfig::BuildAndRunIfNoErrors, - Triple::host(), + Triple::host().into(), None, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), LinkType::Executable, @@ -64,7 +64,7 @@ fn main() -> io::Result<()> { matches, &subcommands, BuildConfig::BuildAndRun, - Triple::host(), + Triple::host().into(), None, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), LinkType::Executable, @@ -77,7 +77,7 @@ fn main() -> io::Result<()> { } Some((CMD_TEST, matches)) => { if matches.contains_id(ROC_FILE) { - test(matches, Triple::host()) + test(matches, Triple::host().into()) } else { eprintln!("What .roc file do you want to test? Specify it at the end of the `roc test` command."); @@ -90,7 +90,7 @@ fn main() -> io::Result<()> { matches, &subcommands, BuildConfig::BuildAndRunIfNoErrors, - Triple::host(), + Triple::host().into(), None, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), LinkType::Executable, @@ -130,7 +130,7 @@ fn main() -> io::Result<()> { roc_linker::generate_stub_lib( input_path, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), - &target.to_triple(), + target, function_kind, ); Ok(0) @@ -142,24 +142,22 @@ fn main() -> io::Result<()> { .and_then(|s| Target::from_str(s).ok()) .unwrap_or_default(); - let triple = target.to_triple(); let function_kind = FunctionKind::LambdaSet; let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib( input_path, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), - &triple, + target, function_kind, ); // TODO: pipeline the executable location through here. // Currently it is essentally hardcoded as platform_path/dynhost. roc_linker::preprocess_host( - &triple, + target, &platform_path.with_file_name("main.roc"), // The target triple string must be derived from the triple to convert from the generic // `system` target to the exact specific target. - &platform_path - .with_file_name(format!("{}.rh", get_target_triple_str(&triple).unwrap())), + &platform_path.with_file_name(format!("{}.rh", target)), &stub_lib, &stub_dll_symbols, ); @@ -184,7 +182,7 @@ fn main() -> io::Result<()> { matches, &subcommands, BuildConfig::BuildOnly, - target.to_triple(), + target, out_path, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), link_type, diff --git a/crates/compiler/build/src/link.rs b/crates/compiler/build/src/link.rs index 441d3426c8..8f34671338 100644 --- a/crates/compiler/build/src/link.rs +++ b/crates/compiler/build/src/link.rs @@ -1,9 +1,10 @@ -use crate::target::{arch_str, target_zig_str}; +use crate::target::arch_str; use libloading::{Error, Library}; use roc_command_utils::{cargo, clang, rustup, zig}; use roc_debug_flags; use roc_error_macros::internal_error; use roc_mono::ir::OptLevel; +use roc_target::{Architecture, OperatingSystem, Target}; use std::collections::HashMap; use std::ffi::OsString; use std::fs::DirEntry; @@ -11,7 +12,6 @@ use std::io; use std::path::{Path, PathBuf}; use std::process::{self, Child, Command}; use std::{env, fs}; -use target_lexicon::{Architecture, OperatingSystem, Triple}; use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH}; pub use roc_linker::LinkType; @@ -28,46 +28,33 @@ pub enum LinkingStrategy { /// input_paths can include the host as well as the app. e.g. &["host.o", "roc_app.o"] pub fn link( - target: &Triple, + target: Target, output_path: PathBuf, input_paths: &[&str], link_type: LinkType, ) -> io::Result<(Child, PathBuf)> { - match target { - Triple { - architecture: Architecture::Wasm32, - .. - } => link_wasm32(target, output_path, input_paths, link_type), - Triple { - operating_system: OperatingSystem::Linux, - .. - } => link_linux(target, output_path, input_paths, link_type), - Triple { - operating_system: OperatingSystem::Darwin, - .. - } => link_macos(target, output_path, input_paths, link_type), - Triple { - operating_system: OperatingSystem::Windows, - .. - } => link_windows(target, output_path, input_paths, link_type), + match target.arch_os() { + (Architecture::Wasm32, _) => link_wasm32(target, output_path, input_paths, link_type), + (_, OperatingSystem::Linux) => link_linux(target, output_path, input_paths, link_type), + (_, OperatingSystem::Mac) => link_macos(target, output_path, input_paths, link_type), + (_, OperatingSystem::Windows) => link_windows(output_path, input_paths, link_type), _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), } } /// Same format as the precompiled host filename, except with a file extension like ".o" or ".obj" -pub fn legacy_host_file(target: &Triple, platform_main_roc: &Path) -> Option { - let os = roc_target::OperatingSystem::from(target.operating_system); - let lib_ext = os.static_library_file_ext(); +pub fn legacy_host_file(target: Target, platform_main_roc: &Path) -> PathBuf { + let lib_ext = target.static_library_file_ext(); - let file_name = roc_linker::preprocessed_host_filename(target)? + let file_name = roc_linker::preprocessed_host_filename(target) .replace(roc_linker::PRECOMPILED_HOST_EXT, lib_ext); let lib_path = platform_main_roc.with_file_name(file_name); if lib_path.exists() { - Some(lib_path) + lib_path } else { - let obj_ext = os.object_file_ext(); - Some(lib_path.with_extension(obj_ext)) + let obj_ext = target.object_file_ext(); + lib_path.with_extension(obj_ext) } } @@ -316,7 +303,7 @@ pub fn build_zig_host_wasm32( #[allow(clippy::too_many_arguments)] pub fn build_c_host_native( - target: &Triple, + target: Target, env_path: &str, env_home: &str, env_cpath: &str, @@ -335,7 +322,7 @@ pub fn build_c_host_native( .args(sources) .args(["-o", dest]); if let Some(shared_lib_path) = shared_lib_path { - match target.operating_system { + match target.operating_system() { OperatingSystem::Windows => { // just use zig as a C compiler @@ -347,7 +334,7 @@ pub fn build_c_host_native( env_home, dest, sources[0], - get_target_str(target), + "native", opt_level, Some(shared_lib_path), builtins_host_path, @@ -406,7 +393,7 @@ pub fn build_swift_host_native( .env("HOME", env_home); match arch { - Architecture::Aarch64(_) => command.arg("-arm64"), + Architecture::Aarch64 => command.arg("-arm64"), _ => command.arg(format!("-{arch}")), }; @@ -437,7 +424,7 @@ pub fn build_swift_host_native( pub fn rebuild_host( opt_level: OptLevel, - target: &Triple, + target: Target, platform_main_roc: &Path, shared_lib_path: Option<&Path>, ) -> PathBuf { @@ -450,14 +437,12 @@ pub fn rebuild_host( let swift_host_src = platform_main_roc.with_file_name("host.swift"); let swift_host_header_src = platform_main_roc.with_file_name("host.h"); - let os = roc_target::OperatingSystem::from(target.operating_system); - let executable_extension = match os { - roc_target::OperatingSystem::Windows => "exe", - roc_target::OperatingSystem::Unix => "", - roc_target::OperatingSystem::Wasi => "", + let executable_extension = match target.operating_system() { + OperatingSystem::Windows => "exe", + _ => "", }; - let host_dest = if matches!(target.architecture, Architecture::Wasm32) { + let host_dest = if matches!(target.architecture(), Architecture::Wasm32) { if matches!(opt_level, OptLevel::Development) { platform_main_roc.with_extension("o") } else { @@ -468,7 +453,7 @@ pub fn rebuild_host( .with_file_name("dynhost") .with_extension(executable_extension) } else { - legacy_host_file(target, platform_main_roc).unwrap() + legacy_host_file(target, platform_main_roc) }; let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string()); @@ -480,7 +465,7 @@ pub fn rebuild_host( if zig_host_src.exists() { // Compile host.zig - let zig_cmd = match target.architecture { + let zig_cmd = match target.architecture() { Architecture::Wasm32 => { let emit_bin = if matches!(opt_level, OptLevel::Development) { format!("-femit-bin={}", host_dest.to_str().unwrap()) @@ -501,12 +486,12 @@ pub fn rebuild_host( &env_home, host_dest.to_str().unwrap(), zig_host_src.to_str().unwrap(), - get_target_str(target), + "native", opt_level, shared_lib_path, builtins_host_tempfile.path(), ), - Architecture::X86_32(_) => build_zig_host_native( + Architecture::X86_32 => build_zig_host_native( &env_path, &env_home, host_dest.to_str().unwrap(), @@ -516,17 +501,17 @@ pub fn rebuild_host( shared_lib_path, builtins_host_tempfile.path(), ), - Architecture::Aarch64(_) => build_zig_host_native( + Architecture::Aarch64 => build_zig_host_native( &env_path, &env_home, host_dest.to_str().unwrap(), zig_host_src.to_str().unwrap(), - target_zig_str(target), + "native", opt_level, shared_lib_path, builtins_host_tempfile.path(), ), - _ => internal_error!("Unsupported architecture {:?}", target.architecture), + _ => internal_error!("Unsupported architecture {:?}", target.architecture()), }; run_build_command(zig_cmd, "host.zig", 0); @@ -714,7 +699,7 @@ pub fn rebuild_host( swift_host_header_src .exists() .then(|| swift_host_header_src.to_str().unwrap()), - target.architecture, + target.architecture(), ); run_build_command(swiftc_cmd, "host.swift", 0); @@ -784,16 +769,6 @@ fn find_in_folder_or_subfolders(path: &PathBuf, folder_to_find: &str) -> Vec &str { - if target.operating_system == OperatingSystem::Windows - && target.environment == target_lexicon::Environment::Gnu - { - "x86_64-windows-gnu" - } else { - "native" - } -} - fn nix_paths() -> Vec { let mut paths = vec![]; @@ -862,12 +837,12 @@ fn extra_link_flags() -> Vec { } fn link_linux( - target: &Triple, + target: Target, output_path: PathBuf, input_paths: &[&str], link_type: LinkType, ) -> io::Result<(Child, PathBuf)> { - let architecture = format!("{}-linux-gnu", target.architecture); + let architecture = format!("{}-linux-gnu", target.architecture()); // Command::new("cp") // .args(&[input_paths[0], "/home/folkertdev/roc/wasm/host.o"]) @@ -879,7 +854,7 @@ fn link_linux( // .output() // .unwrap(); - if let Architecture::X86_32(_) = target.architecture { + if let Architecture::X86_32 = target.architecture() { return Ok(( zig() .args(["build-exe"]) @@ -971,7 +946,7 @@ fn link_linux( scrt1_path.to_string_lossy(), ); - let ld_linux_path = match target.architecture { + let ld_linux_path = match target.architecture() { Architecture::X86_64 => { // give preference to nix_path if it's defined, this prevents bugs if let Some(nix_glibc_path) = nix_glibc_path_opt() { @@ -983,10 +958,10 @@ fn link_linux( build_path_or_panic(["/lib64", "ld-linux-x86-64.so.2"]) } } - Architecture::Aarch64(_) => build_path_or_panic(["/lib", "ld-linux-aarch64.so.1"]), + Architecture::Aarch64 => build_path_or_panic(["/lib", "ld-linux-aarch64.so.1"]), _ => internal_error!( "TODO gracefully handle unsupported linux architecture: {:?}", - target.architecture + target.architecture() ), }; @@ -1083,7 +1058,7 @@ fn link_linux( } fn link_macos( - target: &Triple, + target: Target, output_path: PathBuf, input_paths: &[&str], link_type: LinkType, @@ -1100,9 +1075,9 @@ fn link_macos( LinkType::None => internal_error!("link_macos should not be called with link type of none"), }; - let arch = match target.architecture { - Architecture::Aarch64(_) => "arm64".to_string(), - _ => target.architecture.to_string(), + let arch = match target.architecture() { + Architecture::Aarch64 => "arm64".to_string(), + _ => target.architecture().to_string(), }; let mut ld_command = Command::new("ld"); @@ -1177,8 +1152,8 @@ fn link_macos( let mut ld_child = ld_command.spawn()?; - match target.architecture { - Architecture::Aarch64(_) => { + match target.architecture() { + Architecture::Aarch64 => { ld_child.wait()?; let mut codesign_cmd = Command::new("codesign"); @@ -1214,7 +1189,7 @@ fn get_macos_version() -> String { } fn link_wasm32( - _target: &Triple, + _target: Target, output_path: PathBuf, input_paths: &[&str], _link_type: LinkType, @@ -1249,7 +1224,6 @@ fn link_wasm32( } fn link_windows( - target: &Triple, output_path: PathBuf, input_paths: &[&str], link_type: LinkType, @@ -1282,7 +1256,7 @@ fn link_windows( .args(input_paths) .args([ "-target", - get_target_str(target), + "native", "--subsystem", "console", "-lc", @@ -1298,7 +1272,7 @@ fn link_windows( pub fn llvm_module_to_dylib( module: &inkwell::module::Module, - target: &Triple, + target: Target, opt_level: OptLevel, ) -> Result { use crate::target::{self, convert_opt_level}; @@ -1322,7 +1296,7 @@ pub fn llvm_module_to_dylib( // Link app.o into a dylib - e.g. app.so or app.dylib let (mut child, dylib_path) = link( - &Triple::host(), + target, app_o_file.clone(), &[app_o_file.to_str().unwrap()], LinkType::Dylib, @@ -1339,7 +1313,7 @@ pub fn llvm_module_to_dylib( // Load the dylib let path = dylib_path.as_path().to_str().unwrap(); - if matches!(target.architecture, Architecture::Aarch64(_)) { + if matches!(target.architecture(), Architecture::Aarch64) { // On AArch64 darwin machines, calling `ldopen` on Roc-generated libs from multiple threads // sometimes fails with // cannot dlopen until fork() handlers have completed diff --git a/crates/compiler/build/src/program.rs b/crates/compiler/build/src/program.rs index f4a3d87eb2..767ac6c4fc 100644 --- a/crates/compiler/build/src/program.rs +++ b/crates/compiler/build/src/program.rs @@ -17,7 +17,7 @@ use roc_reporting::{ cli::{report_problems, Problems}, report::{RenderTarget, DEFAULT_PALETTE}, }; -use roc_target::{OperatingSystem, TargetInfo}; +use roc_target::{Architecture, Target}; use std::ffi::OsStr; use std::ops::Deref; use std::{ @@ -25,7 +25,6 @@ use std::{ thread::JoinHandle, time::{Duration, Instant}, }; -use target_lexicon::Triple; #[cfg(feature = "target-wasm32")] use roc_collections::all::MutSet; @@ -96,7 +95,7 @@ pub fn gen_from_mono_module<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, roc_file_path: &Path, - target: &target_lexicon::Triple, + target: Target, code_gen_options: CodeGenOptions, preprocessed_host_path: &Path, wasm_dev_stack_bytes: Option, @@ -146,7 +145,7 @@ fn gen_from_mono_module_llvm<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, roc_file_path: &Path, - target: &target_lexicon::Triple, + target: Target, opt_level: OptLevel, backend_mode: LlvmBackendMode, emit_debug_info: bool, @@ -162,7 +161,6 @@ fn gen_from_mono_module_llvm<'a>( let all_code_gen_start = Instant::now(); // Generate the binary - let target_info = roc_target::TargetInfo::from(target); let context = Context::create(); let module = arena.alloc(module_from_builtins(target, &context, "app")); @@ -210,7 +208,7 @@ fn gen_from_mono_module_llvm<'a>( context: &context, interns: loaded.interns, module, - target_info, + target, mode: backend_mode, exposed_to_host: loaded @@ -387,9 +385,8 @@ fn gen_from_mono_module_llvm<'a>( } // Emit the .o file - use target_lexicon::Architecture; - match target.architecture { - Architecture::X86_64 | Architecture::X86_32(_) | Architecture::Aarch64(_) => { + match target.architecture() { + Architecture::X86_64 | Architecture::X86_32 | Architecture::Aarch64 => { let reloc = RelocMode::PIC; let target_machine = target::target_machine(target, convert_opt_level(opt_level), reloc).unwrap(); @@ -405,7 +402,7 @@ fn gen_from_mono_module_llvm<'a>( } _ => internal_error!( "TODO gracefully handle unsupported architecture: {:?}", - target.architecture + target.architecture() ), } }; @@ -432,21 +429,19 @@ fn gen_from_mono_module_llvm<'a>( fn gen_from_mono_module_dev<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, - target: &target_lexicon::Triple, + target: Target, preprocessed_host_path: &Path, wasm_dev_stack_bytes: Option, backend_mode: AssemblyBackendMode, ) -> GenFromMono<'a> { - use target_lexicon::Architecture; - - match target.architecture { + match target.architecture() { Architecture::Wasm32 => gen_from_mono_module_dev_wasm32( arena, loaded, preprocessed_host_path, wasm_dev_stack_bytes, ), - Architecture::X86_64 | Architecture::Aarch64(_) => { + Architecture::X86_64 | Architecture::Aarch64 => { gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode) } _ => todo!(), @@ -457,15 +452,13 @@ fn gen_from_mono_module_dev<'a>( pub fn gen_from_mono_module_dev<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, - target: &target_lexicon::Triple, + target: Target, _host_input_path: &Path, _wasm_dev_stack_bytes: Option, backend_mode: AssemblyBackendMode, ) -> GenFromMono<'a> { - use target_lexicon::Architecture; - - match target.architecture { - Architecture::X86_64 | Architecture::Aarch64(_) => { + match target.architecture() { + Architecture::X86_64 | Architecture::Aarch64 => { gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode) } _ => todo!(), @@ -549,7 +542,7 @@ fn gen_from_mono_module_dev_wasm32<'a>( fn gen_from_mono_module_dev_assembly<'a>( arena: &'a bumpalo::Bump, loaded: MonomorphizedModule<'a>, - target: &target_lexicon::Triple, + target: Target, backend_mode: AssemblyBackendMode, ) -> GenFromMono<'a> { let all_code_gen_start = Instant::now(); @@ -694,12 +687,10 @@ pub fn handle_loading_problem(problem: LoadingProblem) -> std::io::Result { } pub fn standard_load_config( - target: &Triple, + target: Target, order: BuildOrdering, threading: Threading, ) -> LoadConfig { - let target_info = TargetInfo::from(target); - let exec_mode = match order { BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck, BuildOrdering::AlwaysBuild => ExecutionMode::Executable, @@ -717,7 +708,7 @@ pub fn standard_load_config( }; LoadConfig { - target_info, + target, function_kind, render: RenderTarget::ColorTerminal, palette: DEFAULT_PALETTE, @@ -729,7 +720,7 @@ pub fn standard_load_config( #[allow(clippy::too_many_arguments)] pub fn build_file<'a>( arena: &'a Bump, - target: &Triple, + target: Target, app_module_path: PathBuf, code_gen_options: CodeGenOptions, emit_timings: bool, @@ -767,7 +758,7 @@ pub fn build_file<'a>( #[allow(clippy::too_many_arguments)] fn build_loaded_file<'a>( arena: &'a Bump, - target: &Triple, + target: Target, app_module_path: PathBuf, code_gen_options: CodeGenOptions, emit_timings: bool, @@ -779,8 +770,6 @@ fn build_loaded_file<'a>( compilation_start: Instant, out_path: Option<&Path>, ) -> Result, BuildFileError<'a>> { - let operating_system = roc_target::OperatingSystem::from(target.operating_system); - let platform_main_roc = match &loaded.entry_point { EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(), _ => unreachable!(), @@ -792,9 +781,9 @@ fn build_loaded_file<'a>( if is_platform_prebuilt && linking_strategy == LinkingStrategy::Surgical { // Fallback to legacy linking if the preprocessed host file does not exist, but a legacy host does exist. - let preprocessed_host_path = platform_main_roc - .with_file_name(roc_linker::preprocessed_host_filename(target).unwrap()); - let legacy_host_path = legacy_host_file(target, &platform_main_roc).unwrap(); + let preprocessed_host_path = + platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target)); + let legacy_host_path = legacy_host_file(target, &platform_main_roc); if !preprocessed_host_path.exists() && legacy_host_path.exists() { linking_strategy = LinkingStrategy::Legacy; } @@ -802,15 +791,15 @@ fn build_loaded_file<'a>( // the preprocessed host is stored beside the platform's main.roc let preprocessed_host_path = if linking_strategy == LinkingStrategy::Legacy { - if let roc_target::OperatingSystem::Wasi = operating_system { + if target == Target::Wasm32 { // when compiling a wasm application, we implicitly assume here that the host is in zig // and has a file called "host.zig" platform_main_roc.with_file_name("host.zig") } else { - legacy_host_file(target, &platform_main_roc).unwrap() + legacy_host_file(target, &platform_main_roc) } } else { - platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap()) + platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target)) }; let output_exe_path = match out_path { @@ -841,22 +830,12 @@ fn build_loaded_file<'a>( if ends_with_sep { let filename = app_module_path.file_name().unwrap_or_default(); - with_output_extension( - &path.join(filename), - operating_system, - linking_strategy, - link_type, - ) + with_output_extension(&path.join(filename), target, linking_strategy, link_type) } else { path.to_path_buf() } } - None => with_output_extension( - &app_module_path, - operating_system, - linking_strategy, - link_type, - ), + None => with_output_extension(&app_module_path, target, linking_strategy, link_type), }; // We don't need to spawn a rebuild thread when using a prebuilt host. @@ -1018,13 +997,13 @@ fn build_loaded_file<'a>( std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap(); } (LinkingStrategy::Legacy, _) => { - let extension = if matches!(operating_system, roc_target::OperatingSystem::Wasi) { + let extension = if target == Target::Wasm32 { // Legacy linker is only by used llvm wasm backend, not dev. // llvm wasm backend directly emits a bitcode file when targeting wasi, not a `.o` or `.wasm` file. // If we set the extension wrong, zig will print a ton of warnings when linking. "bc" } else { - operating_system.object_file_ext() + target.object_file_ext() }; let app_o_file = tempfile::Builder::new() .prefix("roc_app") @@ -1124,10 +1103,9 @@ fn spawn_rebuild_thread( platform_main_roc: PathBuf, preprocessed_host_path: PathBuf, output_exe_path: PathBuf, - target: &Triple, + target: Target, dll_stub_symbols: Vec, ) -> std::thread::JoinHandle { - let thread_local_target = target.clone(); std::thread::spawn(move || { // Printing to stderr because we want stdout to contain only the output of the roc program. // We are aware of the trade-offs. @@ -1138,19 +1116,14 @@ fn spawn_rebuild_thread( match linking_strategy { LinkingStrategy::Additive => { - let host_dest = rebuild_host( - opt_level, - &thread_local_target, - platform_main_roc.as_path(), - None, - ); + let host_dest = rebuild_host(opt_level, target, platform_main_roc.as_path(), None); preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path); } LinkingStrategy::Surgical => { build_and_preprocess_host_lowlevel( opt_level, - &thread_local_target, + target, platform_main_roc.as_path(), preprocessed_host_path.as_path(), &dll_stub_symbols, @@ -1161,12 +1134,7 @@ fn spawn_rebuild_thread( std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); } LinkingStrategy::Legacy => { - rebuild_host( - opt_level, - &thread_local_target, - platform_main_roc.as_path(), - None, - ); + rebuild_host(opt_level, target, platform_main_roc.as_path(), None); } } @@ -1176,7 +1144,7 @@ fn spawn_rebuild_thread( pub fn build_and_preprocess_host( opt_level: OptLevel, - target: &Triple, + target: Target, platform_main_roc: &Path, preprocessed_host_path: &Path, exposed_symbols: roc_linker::ExposedSymbols, @@ -1194,7 +1162,7 @@ pub fn build_and_preprocess_host( fn build_and_preprocess_host_lowlevel( opt_level: OptLevel, - target: &Triple, + target: Target, platform_main_roc: &Path, preprocessed_host_path: &Path, stub_dll_symbols: &[String], @@ -1227,12 +1195,12 @@ pub fn check_file<'a>( // only used for generating errors. We don't do code generation, so hardcoding should be fine // we need monomorphization for when exhaustiveness checking - let target_info = TargetInfo::default_x86_64(); + let target = Target::LinuxX64; // Step 1: compile the app and generate the .o file let load_config = LoadConfig { - target_info, + target, // TODO: we may not want this for just checking. function_kind: FunctionKind::LambdaSet, // TODO: expose this from CLI? @@ -1295,7 +1263,7 @@ pub fn build_str_test<'a>( app_module_source: &'a str, assume_prebuild: bool, ) -> Result, BuildFileError<'a>> { - let triple = target_lexicon::Triple::host(); + let target = target_lexicon::Triple::host().into(); let code_gen_options = CodeGenOptions { backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary), @@ -1314,7 +1282,7 @@ pub fn build_str_test<'a>( let build_ordering = BuildOrdering::AlwaysBuild; let threading = Threading::AtMost(2); - let load_config = standard_load_config(&triple, build_ordering, threading); + let load_config = standard_load_config(target, build_ordering, threading); let compilation_start = std::time::Instant::now(); @@ -1331,7 +1299,7 @@ pub fn build_str_test<'a>( build_loaded_file( arena, - &triple, + target, app_module_path.to_path_buf(), code_gen_options, emit_timings, @@ -1347,15 +1315,15 @@ pub fn build_str_test<'a>( fn with_output_extension( path: &Path, - os: OperatingSystem, + target: Target, linking_strategy: LinkingStrategy, link_type: LinkType, ) -> PathBuf { match (linking_strategy, link_type) { (LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => { // Additive linking and no linking both output the object file type. - path.with_extension(os.object_file_ext()) + path.with_extension(target.object_file_ext()) } - _ => path.with_extension(os.executable_file_ext().unwrap_or_default()), + _ => path.with_extension(target.executable_file_ext().unwrap_or_default()), } } diff --git a/crates/compiler/build/src/target.rs b/crates/compiler/build/src/target.rs index 227e17895d..c77ea22e59 100644 --- a/crates/compiler/build/src/target.rs +++ b/crates/compiler/build/src/target.rs @@ -1,121 +1,65 @@ use inkwell::{ - targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple}, + targets::{ + CodeModel, InitializationConfig, RelocMode, Target as LlvmTarget, TargetMachine, + TargetTriple, + }, OptimizationLevel, }; use roc_error_macros::internal_error; use roc_mono::ir::OptLevel; -use target_lexicon::{Architecture, Environment, OperatingSystem, Triple}; +use roc_target::{Architecture, Target}; -pub fn target_triple_str(target: &Triple) -> &'static str { +pub fn target_triple_str(target: Target) -> &'static str { // Best guide I've found on how to determine these magic strings: // // https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures match target { - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Linux, - .. - } => "x86_64-unknown-linux-gnu", - Triple { - architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386), - operating_system: OperatingSystem::Linux, - .. - } => "i386-unknown-linux-gnu", - Triple { - architecture: Architecture::Wasm32, - .. - } => "wasm32-unknown-unknown", - Triple { - architecture: Architecture::Aarch64(_), - operating_system: OperatingSystem::Linux, - .. - } => "aarch64-unknown-linux-gnu", - Triple { - architecture: Architecture::Aarch64(_), - operating_system: OperatingSystem::Darwin, - .. - } => "aarch64-apple-darwin", - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Darwin, - .. - } => "x86_64-unknown-darwin10", - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Windows, - .. - } => "x86_64-pc-windows-gnu", + Target::LinuxArm64 => "aarch64-unknown-linux-gnu", + Target::LinuxX32 => "i386-unknown-linux-gnu", + Target::LinuxX64 => "x86_64-unknown-linux-gnu", + Target::MacArm64 => "aarch64-apple-darwin", + Target::MacX64 => "x86_64-unknown-darwin10", + Target::Wasm32 => "wasm32-unknown-unknown", + Target::WinX64 => "x86_64-pc-windows-gnu", _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), } } -pub fn target_zig_str(target: &Triple) -> &'static str { +pub fn target_zig_str(target: Target) -> &'static str { // Zig has its own architecture mappings, defined here: // https://github.com/ziglang/zig/blob/master/tools/process_headers.zig // // and an open proposal to unify them with the more typical "target triples": // https://github.com/ziglang/zig/issues/4911 match target { - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Linux, - environment: Environment::Musl, - .. - } => "x86_64-linux-musl", - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Linux, - .. - } => "x86_64-linux-gnu", - Triple { - architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386), - operating_system: OperatingSystem::Linux, - environment: Environment::Musl, - .. - } => "i386-linux-musl", - Triple { - architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386), - operating_system: OperatingSystem::Linux, - .. - } => "i386-linux-gnu", - Triple { - architecture: Architecture::Aarch64(_), - operating_system: OperatingSystem::Linux, - .. - } => "aarch64-linux-gnu", - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Darwin, - .. - } => "x86_64-macos-none", - Triple { - architecture: Architecture::Aarch64(_), - operating_system: OperatingSystem::Darwin, - .. - } => "aarch64-macos-none", + Target::LinuxArm64 => "aarch64-linux-gnu", + Target::LinuxX32 => "i386-linux-gnu", + Target::LinuxX64 => "x86_64-linux-gnu", + Target::MacArm64 => "aarch64-macos-none", + Target::MacX64 => "x86_64-macos-none", _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), } } -pub fn init_arch(target: &Triple) { - match target.architecture { - Architecture::X86_64 | Architecture::X86_32(_) +pub fn init_arch(target: Target) { + match target.architecture() { + Architecture::X86_64 | Architecture::X86_32 if cfg!(any(feature = "target-x86", feature = "target-x86_64")) => { - Target::initialize_x86(&InitializationConfig::default()); + LlvmTarget::initialize_x86(&InitializationConfig::default()); } - Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => { - Target::initialize_aarch64(&InitializationConfig::default()); + Architecture::Aarch64 if cfg!(feature = "target-aarch64") => { + LlvmTarget::initialize_aarch64(&InitializationConfig::default()); } - Architecture::Arm(_) if cfg!(feature = "target-arm") => { - Target::initialize_arm(&InitializationConfig::default()); + Architecture::Aarch32 if cfg!(feature = "target-arm") => { + LlvmTarget::initialize_arm(&InitializationConfig::default()); } Architecture::Wasm32 if cfg!(feature = "target-wasm32") => { - Target::initialize_webassembly(&InitializationConfig::default()); + LlvmTarget::initialize_webassembly(&InitializationConfig::default()); } _ => internal_error!( "TODO gracefully handle unsupported target architecture: {:?}", - target.architecture + target.architecture() ), } } @@ -123,25 +67,25 @@ pub fn init_arch(target: &Triple) { /// NOTE: arch_str is *not* the same as the beginning of the magic target triple /// string! For example, if it's "x86-64" here, the magic target triple string /// will begin with "x86_64" (with an underscore) instead. -pub fn arch_str(target: &Triple) -> &'static str { +pub fn arch_str(target: Target) -> &'static str { // Best guide I've found on how to determine these magic strings: // // https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures - match target.architecture { - Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64", - Architecture::X86_32(_) if cfg!(feature = "target-x86") => "x86", - Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => "aarch64", - Architecture::Arm(_) if cfg!(feature = "target-arm") => "arm", - Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32", + match target.architecture() { + roc_target::Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64", + roc_target::Architecture::X86_32 if cfg!(feature = "target-x86") => "x86", + roc_target::Architecture::Aarch64 if cfg!(feature = "target-aarch64") => "aarch64", + roc_target::Architecture::Aarch32 if cfg!(feature = "target-arm") => "arm", + roc_target::Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32", _ => internal_error!( "TODO gracefully handle unsupported target architecture: {:?}", - target.architecture + target.architecture() ), } } pub fn target_machine( - target: &Triple, + target: Target, opt: OptimizationLevel, reloc: RelocMode, ) -> Option { @@ -150,11 +94,7 @@ pub fn target_machine( init_arch(target); let code_model = match target { - Triple { - operating_system: OperatingSystem::Darwin, - architecture: Architecture::Aarch64(_), - .. - } => { + Target::MacArm64 => { // We used to have a problem that LLVM 12 would not compile our programs without a large code model. // The reason was not totally clear to us, but one guess is a few special-cases in // llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (instructions) @@ -168,7 +108,7 @@ pub fn target_machine( _ => CodeModel::Default, }; - Target::from_name(arch).unwrap().create_target_machine( + LlvmTarget::from_name(arch).unwrap().create_target_machine( &TargetTriple::create(target_triple_str(target)), "generic", "", diff --git a/crates/compiler/builtins/roc/List.roc b/crates/compiler/builtins/roc/List.roc index d8b733c248..ee6b45cff6 100644 --- a/crates/compiler/builtins/roc/List.roc +++ b/crates/compiler/builtins/roc/List.roc @@ -372,7 +372,7 @@ prependIfOk = \list, result -> ## Returns the length of the list - the number of elements it contains. ## ## One [List] can store up to `Num.maxI64` elements on 64-bit targets and `Num.maxI32` on 32-bit targets like wasm. -## This means the #U64 this function returns can always be safely converted to #I64 or #I32, depending on the target. +## This means the #U64 this function returns can always be safely converted to #I64 or #I32, depending on the target. len : List * -> U64 ## Create a list with space for at least capacity elements diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index effe436b00..d2e7e178e6 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -1,5 +1,5 @@ use roc_module::symbol::Symbol; -use roc_target::TargetInfo; +use roc_target::Target; use std::ops::Index; #[derive(Debug, Default, Copy, Clone)] @@ -38,7 +38,7 @@ impl FloatWidth { } } - pub const fn alignment_bytes(&self, target_info: TargetInfo) -> u32 { + pub const fn alignment_bytes(&self, target: Target) -> u32 { use roc_target::Architecture::*; use FloatWidth::*; @@ -47,7 +47,7 @@ impl FloatWidth { // the compiler is targeting (e.g. what the Roc code will be compiled to). match self { F32 => 4, - F64 => match target_info.architecture { + F64 => match target.architecture() { X86_64 | Aarch64 | Wasm32 => 8, X86_32 | Aarch32 => 4, }, @@ -107,7 +107,7 @@ impl IntWidth { } } - pub const fn alignment_bytes(&self, target_info: TargetInfo) -> u32 { + pub const fn alignment_bytes(&self, target: Target) -> u32 { use roc_target::Architecture; use IntWidth::*; @@ -118,7 +118,7 @@ impl IntWidth { U8 | I8 => 1, U16 | I16 => 2, U32 | I32 => 4, - U64 | I64 => match target_info.architecture { + U64 | I64 => match target.architecture() { Architecture::X86_64 | Architecture::Aarch64 | Architecture::Aarch32 @@ -131,7 +131,7 @@ impl IntWidth { // // however, rust does not always think that this is true // Our alignmets here are correct, but they will not match rust/zig/llvm until they update to llvm version 18. - match target_info.architecture { + match target.architecture() { Architecture::X86_64 | Architecture::Aarch64 | Architecture::X86_32 => 16, Architecture::Aarch32 | Architecture::Wasm32 => 8, } diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index 2ba1abc46a..973a9371cd 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -17,7 +17,7 @@ use roc_mono::layout::{ TagIdIntType, UnionLayout, }; use roc_mono::low_level::HigherOrder; -use roc_target::TargetInfo; +use roc_target::Target; use std::marker::PhantomData; pub(crate) mod aarch64; @@ -790,7 +790,7 @@ pub fn new_backend_64bit< CC: CallConv, >( env: &'r Env<'a>, - target_info: TargetInfo, + target: Target, interns: &'r mut Interns, layout_interner: &'r mut STLayoutInterner<'a>, ) -> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC> { @@ -800,7 +800,7 @@ pub fn new_backend_64bit< env, interns, layout_interner, - helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id), + helper_proc_gen: CodeGenHelp::new(env.arena, target, env.module_id), helper_proc_symbols: bumpalo::vec![in env.arena], caller_procs: bumpalo::vec![in env.arena], proc_name: None, @@ -812,7 +812,7 @@ pub fn new_backend_64bit< free_map: MutMap::default(), literal_map: MutMap::default(), join_map: MutMap::default(), - storage_manager: storage::new_storage_manager(env, target_info), + storage_manager: storage::new_storage_manager(env, target), } } @@ -853,8 +853,8 @@ impl< fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation> { &mut self.relocs } - fn target_info(&self) -> TargetInfo { - self.storage_manager.target_info + fn target(&self) -> Target { + self.storage_manager.target } fn module_interns_helpers_mut( &mut self, @@ -3627,7 +3627,7 @@ impl< // mask out the tag id bits let (unmasked_symbol, unmasked_reg) = - if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + if union_layout.stores_tag_id_as_data(self.storage_manager.target) { (None, ptr_reg) } else { let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); @@ -3728,7 +3728,7 @@ impl< // mask out the tag id bits let (unmasked_symbol, unmasked_reg) = - if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + if union_layout.stores_tag_id_as_data(self.storage_manager.target) { (None, ptr_reg) } else { let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); @@ -4007,8 +4007,8 @@ impl< UnionLayout::Recursive(_) => { let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, sym); - let target_info = self.storage_manager.target_info; - if union_layout.stores_tag_id_as_data(target_info) { + let target = self.storage_manager.target; + if union_layout.stores_tag_id_as_data(target) { let offset = union_layout.tag_id_offset(self.interner()).unwrap() as i32; let ptr_reg = self @@ -4173,7 +4173,7 @@ impl< .unwrap(); let largest_variant = - if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + if union_layout.stores_tag_id_as_data(self.storage_manager.target) { self.layout_interner .insert_direct_no_semantic(LayoutRepr::Struct( self.env.arena.alloc([largest_variant_fields, Layout::U8]), @@ -4214,7 +4214,7 @@ impl< }; // finally, we need to tag the pointer - if union_layout.stores_tag_id_as_data(self.storage_manager.target_info) { + if union_layout.stores_tag_id_as_data(self.storage_manager.target) { // allocate space on the stack for the whole tag payload let scratch_space = self.debug_symbol("scratch_space"); let (data_size, data_alignment) = @@ -4290,7 +4290,7 @@ impl< let other_fields = tags[tag_id as usize]; let stores_tag_id_as_data = - union_layout.stores_tag_id_as_data(self.storage_manager.target_info); + union_layout.stores_tag_id_as_data(self.storage_manager.target); let (largest_variant_fields, _largest_variant_size) = tags .iter() diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index 7943832f04..6042b72b09 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -14,7 +14,7 @@ use roc_mono::{ Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, }, }; -use roc_target::TargetInfo; +use roc_target::Target; use std::cmp::max; use std::marker::PhantomData; use std::rc::Rc; @@ -92,7 +92,7 @@ pub struct StorageManager< phantom_cc: PhantomData, phantom_asm: PhantomData, pub(crate) env: &'r Env<'a>, - pub(crate) target_info: TargetInfo, + pub(crate) target: Target, // Data about where each symbol is stored. symbol_storage_map: MutMap>, @@ -137,13 +137,13 @@ pub fn new_storage_manager< CC: CallConv, >( env: &'r Env<'a>, - target_info: TargetInfo, + target: Target, ) -> StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC> { StorageManager { phantom_asm: PhantomData, phantom_cc: PhantomData, env, - target_info, + target, symbol_storage_map: MutMap::default(), allocation_map: MutMap::default(), join_param_map: MutMap::default(), diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 5dbf7995f8..6e8f545ed5 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -28,7 +28,7 @@ use roc_mono::list_element_layout; mod generic64; mod object_builder; pub use object_builder::build_module; -use roc_target::TargetInfo; +use roc_target::Target; mod run_roc; #[derive(Debug, Clone, Copy)] @@ -312,7 +312,7 @@ trait Backend<'a> { fn interns_mut(&mut self) -> &mut Interns; fn interner(&self) -> &STLayoutInterner<'a>; fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation>; - fn target_info(&self) -> TargetInfo; + fn target(&self) -> Target; fn interner_mut(&mut self) -> &mut STLayoutInterner<'a> { self.module_interns_helpers_mut().1 diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index c86907cfdd..54ca0b2924 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -14,8 +14,7 @@ use roc_module::symbol::Interns; use roc_mono::ir::{Call, CallSpecId, Expr, UpdateModeId}; use roc_mono::ir::{Proc, ProcLayout, Stmt}; use roc_mono::layout::{LambdaName, Layout, LayoutIds, LayoutInterner, STLayoutInterner}; -use roc_target::TargetInfo; -use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Triple}; +use roc_target::Target; // This is used by some code below which is currently commented out. // See that code for more details! @@ -27,7 +26,7 @@ pub fn build_module<'a, 'r>( env: &'r Env<'a>, interns: &'r mut Interns, layout_interner: &'r mut STLayoutInterner<'a>, - target: &Triple, + target: Target, procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>, ) -> Object<'a> { let module_object = build_module_help(env, interns, layout_interner, target, procedures); @@ -49,21 +48,17 @@ fn build_module_help<'a, 'r>( env: &'r Env<'a>, interns: &'r mut Interns, layout_interner: &'r mut STLayoutInterner<'a>, - target: &Triple, + target: Target, procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>, ) -> Object<'a> { match target { - Triple { - architecture: TargetArch::X86_64, - binary_format: TargetBF::Elf, - .. - } if cfg!(feature = "target-x86_64") => { + Target::LinuxX64 if cfg!(feature = "target-x86_64") => { let backend = new_backend_64bit::< x86_64::X86_64GeneralReg, x86_64::X86_64FloatReg, x86_64::X86_64Assembler, x86_64::X86_64SystemV, - >(env, TargetInfo::default_x86_64(), interns, layout_interner); + >(env, target, interns, layout_interner); // Newer version of `ld` require `.note.GNU-stack` for security reasons. // It specifies that we will not execute code stored on the stack. let mut object = @@ -75,17 +70,13 @@ fn build_module_help<'a, 'r>( ); build_object(procedures, backend, object) } - Triple { - architecture: TargetArch::X86_64, - binary_format: TargetBF::Macho, - .. - } if cfg!(feature = "target-x86_64") => { + Target::MacX64 if cfg!(feature = "target-x86_64") => { let backend = new_backend_64bit::< x86_64::X86_64GeneralReg, x86_64::X86_64FloatReg, x86_64::X86_64Assembler, x86_64::X86_64SystemV, - >(env, TargetInfo::default_x86_64(), interns, layout_interner); + >(env, target, interns, layout_interner); build_object( procedures, backend, @@ -96,53 +87,39 @@ fn build_module_help<'a, 'r>( ), ) } - Triple { - architecture: TargetArch::X86_64, - binary_format: TargetBF::Coff, - .. - } if cfg!(feature = "target-x86_64") => { + Target::WinX64 if cfg!(feature = "target-x86_64") => { let backend = new_backend_64bit::< x86_64::X86_64GeneralReg, x86_64::X86_64FloatReg, x86_64::X86_64Assembler, x86_64::X86_64WindowsFastcall, - >(env, TargetInfo::default_x86_64(), interns, layout_interner); + >(env, target, interns, layout_interner); build_object( procedures, backend, Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little), ) } - Triple { - architecture: TargetArch::Aarch64(_), - binary_format: TargetBF::Elf, - .. - } if cfg!(feature = "target-aarch64") => { - let backend = - new_backend_64bit::< - aarch64::AArch64GeneralReg, - aarch64::AArch64FloatReg, - aarch64::AArch64Assembler, - aarch64::AArch64Call, - >(env, TargetInfo::default_aarch64(), interns, layout_interner); + Target::LinuxArm64 if cfg!(feature = "target-aarch64") => { + let backend = new_backend_64bit::< + aarch64::AArch64GeneralReg, + aarch64::AArch64FloatReg, + aarch64::AArch64Assembler, + aarch64::AArch64Call, + >(env, target, interns, layout_interner); build_object( procedures, backend, Object::new(BinaryFormat::Elf, Architecture::Aarch64, Endianness::Little), ) } - Triple { - architecture: TargetArch::Aarch64(_), - binary_format: TargetBF::Macho, - .. - } if cfg!(feature = "target-aarch64") => { - let backend = - new_backend_64bit::< - aarch64::AArch64GeneralReg, - aarch64::AArch64FloatReg, - aarch64::AArch64Assembler, - aarch64::AArch64Call, - >(env, TargetInfo::default_aarch64(), interns, layout_interner); + Target::MacArm64 if cfg!(feature = "target-aarch64") => { + let backend = new_backend_64bit::< + aarch64::AArch64GeneralReg, + aarch64::AArch64FloatReg, + aarch64::AArch64Assembler, + aarch64::AArch64Call, + >(env, target, interns, layout_interner); build_object( procedures, backend, @@ -394,7 +371,7 @@ fn generate_wrapper<'a, B: Backend<'a>>( }; output.add_symbol(symbol); if let Some(sym_id) = output.symbol_id(name) { - let reloc = create_relocation(backend.target_info(), sym_id, offset + proc_offset); + let reloc = create_relocation(backend.target(), sym_id, offset + proc_offset); match output.add_relocation(text_section, reloc) { Ok(obj) => obj, @@ -405,8 +382,8 @@ fn generate_wrapper<'a, B: Backend<'a>>( } } -fn create_relocation(target_info: TargetInfo, symbol: SymbolId, offset: u64) -> write::Relocation { - let (encoding, size, addend, kind) = match target_info.architecture { +fn create_relocation(target: Target, symbol: SymbolId, offset: u64) -> write::Relocation { + let (encoding, size, addend, kind) = match target.architecture() { roc_target::Architecture::Aarch32 => todo!(), roc_target::Architecture::Aarch64 => { if cfg!(target_os = "macos") { @@ -957,7 +934,7 @@ fn build_proc<'a, B: Backend<'a>>( proc: Proc<'a>, ) { let mut local_data_index = 0; - let target_info = backend.target_info(); + let target = backend.target(); let (proc_data, relocs, rc_proc_names) = backend.build_proc(proc, layout_ids); let proc_offset = output.add_symbol_data(proc_id, section_id, &proc_data, 16); for reloc in relocs.iter() { @@ -1078,7 +1055,7 @@ fn build_proc<'a, B: Backend<'a>>( add_undefined_rc_proc(output, name, &rc_proc_names); if let Some(sym_id) = output.symbol_id(name.as_bytes()) { - create_relocation(target_info, sym_id, offset + proc_offset) + create_relocation(target, sym_id, offset + proc_offset) } else { internal_error!("failed to find fn symbol for {:?}", name); } diff --git a/crates/compiler/gen_llvm/src/llvm/align.rs b/crates/compiler/gen_llvm/src/llvm/align.rs index bf7327353b..4370c89576 100644 --- a/crates/compiler/gen_llvm/src/llvm/align.rs +++ b/crates/compiler/gen_llvm/src/llvm/align.rs @@ -21,7 +21,7 @@ impl LlvmAlignment<'_> for IntWidth { // 128-bit integers are not consistently represented by LLVM. // - AArch64 uses 16-byte alignment (https://godbolt.org/z/dYrfG5o4b) // - x86-64 uses 8-byte alignment (https://godbolt.org/z/qj5Mann6b) - let arch = interner.target_info().architecture; + let arch = interner.target().architecture(); match arch { Architecture::X86_64 => 8, _ => 16, @@ -33,7 +33,7 @@ impl LlvmAlignment<'_> for IntWidth { impl<'a> LlvmAlignment<'a> for FloatWidth { fn llvm_alignment_bytes(&self, interner: &STLayoutInterner<'a>) -> u32 { - self.alignment_bytes(interner.target_info()) + self.alignment_bytes(interner.target()) } } @@ -48,7 +48,7 @@ impl<'a> LlvmAlignment<'a> for Builtin<'a> { use std::mem::align_of; use Builtin::*; - let ptr_width = interner.target_info().ptr_width() as u32; + let ptr_width = interner.target().ptr_width() as u32; // for our data structures, what counts is the alignment of the `( ptr, len )` tuple, and // since both of those are one pointer size, the alignment of that structure is a pointer @@ -99,7 +99,7 @@ impl<'a> LlvmAlignment<'a> for UnionLayout<'a> { Recursive(_) | NullableWrapped { .. } | NullableUnwrapped { .. } - | NonNullableUnwrapped(_) => interner.target_info().ptr_width() as u32, + | NonNullableUnwrapped(_) => interner.target().ptr_width() as u32, } } } @@ -120,7 +120,7 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> { .llvm_alignment_bytes(interner), Builtin(builtin) => builtin.llvm_alignment_bytes(interner), RecursivePointer(_) | Ptr(_) | FunctionPointer(_) | Erased(_) => { - interner.target_info().ptr_width() as u32 + interner.target().ptr_width() as u32 } } } diff --git a/crates/compiler/gen_llvm/src/llvm/bitcode.rs b/crates/compiler/gen_llvm/src/llvm/bitcode.rs index 405bf03ec7..513dbfcd51 100644 --- a/crates/compiler/gen_llvm/src/llvm/bitcode.rs +++ b/crates/compiler/gen_llvm/src/llvm/bitcode.rs @@ -37,7 +37,7 @@ pub fn call_bitcode_fn<'ctx>( panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}") }); - if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + if env.target.operating_system() == roc_target::OperatingSystem::Windows { // On windows zig uses a vector type <2xi64> instead of a i128 value let vec_type = env.context.i64_type().vec_type(2); if ret.get_type() == vec_type.into() { @@ -70,7 +70,7 @@ fn call_bitcode_fn_help<'ctx>( let it = args .iter() .map(|x| { - if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + if env.target.operating_system() == roc_target::OperatingSystem::Windows { if x.get_type() == env.context.i128_type().into() { let parent = env .builder @@ -1067,7 +1067,7 @@ pub(crate) fn call_str_bitcode_fn<'ctx>( use bumpalo::collections::Vec; use roc_target::Architecture::*; - match env.target_info.architecture { + match env.target.architecture() { Aarch32 | X86_32 => { let mut arguments: Vec = Vec::with_capacity_in(other_arguments.len() + 2 * strings.len(), env.arena); @@ -1123,7 +1123,7 @@ pub(crate) fn call_list_bitcode_fn<'ctx>( use bumpalo::collections::Vec; use roc_target::Architecture::*; - match env.target_info.architecture { + match env.target.architecture() { Aarch32 | X86_32 => { let mut arguments: Vec = Vec::with_capacity_in(other_arguments.len() + 2 * lists.len(), env.arena); diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index e3b6bc8e47..351c34a9e0 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -52,10 +52,9 @@ use roc_mono::layout::{ RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout, }; use roc_std::RocDec; -use roc_target::{PtrWidth, TargetInfo}; +use roc_target::{PtrWidth, Target}; use std::convert::TryInto; use std::path::Path; -use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple}; use super::convert::{struct_type_from_union_layout, RocUnion}; use super::intrinsics::{ @@ -737,7 +736,7 @@ pub struct Env<'a, 'ctx, 'env> { pub compile_unit: &'env DICompileUnit<'ctx>, pub module: &'ctx Module<'ctx>, pub interns: Interns, - pub target_info: TargetInfo, + pub target: Target, pub mode: LlvmBackendMode, pub exposed_to_host: MutSet, } @@ -750,7 +749,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { pub fn ptr_int(&self) -> IntType<'ctx> { let ctx = self.context; - match self.target_info.ptr_width() { + match self.target.ptr_width() { roc_target::PtrWidth::Bytes4 => ctx.i32_type(), roc_target::PtrWidth::Bytes8 => ctx.i64_type(), } @@ -763,14 +762,14 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { pub fn twice_ptr_int(&self) -> IntType<'ctx> { let ctx = self.context; - match self.target_info.ptr_width() { + match self.target.ptr_width() { roc_target::PtrWidth::Bytes4 => ctx.i64_type(), roc_target::PtrWidth::Bytes8 => ctx.i128_type(), } } pub fn small_str_bytes(&self) -> u32 { - self.target_info.ptr_width() as u32 * 3 + self.target.ptr_width() as u32 * 3 } pub fn build_intrinsic_call( @@ -872,7 +871,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { ) -> CallSiteValue<'ctx> { let false_val = self.context.bool_type().const_int(0, false); - let intrinsic_name = match self.target_info.ptr_width() { + let intrinsic_name = match self.target.ptr_width() { roc_target::PtrWidth::Bytes8 => LLVM_MEMSET_I64, roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32, }; @@ -932,7 +931,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { env: &Env<'a, 'ctx, 'env>, string: BasicValueEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - match env.target_info.ptr_width() { + match env.target.ptr_width() { PtrWidth::Bytes4 => { // we need to pass the string by reference, but we currently hold the value. let alloca = env @@ -1011,48 +1010,29 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { } pub fn module_from_builtins<'ctx>( - target: &target_lexicon::Triple, + target: Target, ctx: &'ctx Context, module_name: &str, ) -> Module<'ctx> { // In the build script for the builtins module, we compile the builtins into LLVM bitcode - let bitcode_bytes: &[u8] = if target == &target_lexicon::Triple::host() { + let bitcode_bytes: &[u8] = if target == target_lexicon::Triple::host().into() { include_bytes!("../../../builtins/bitcode/zig-out/builtins-host.bc") } else { match target { - Triple { - architecture: Architecture::Wasm32, - .. - } => { + Target::Wasm32 => { include_bytes!("../../../builtins/bitcode/zig-out/builtins-wasm32.bc") } - Triple { - architecture: Architecture::X86_32(_), - operating_system: OperatingSystem::Linux, - .. - } => { + Target::LinuxX32 => { include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86.bc") } - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Linux, - .. - } => { + Target::LinuxX64 => { include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86_64.bc") } - Triple { - architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64), - operating_system: OperatingSystem::Linux, - .. - } => { + Target::LinuxArm64 => { include_bytes!("../../../builtins/bitcode/zig-out/builtins-aarch64.bc") } - Triple { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Windows, - .. - } => { + Target::WinX64 => { include_bytes!("../../../builtins/bitcode/zig-out/builtins-windows-x86_64.bc") } _ => panic!("The zig builtins are not currently built for this target: {target:?}"), @@ -1416,7 +1396,7 @@ fn build_string_literal<'ctx>( let alloca = const_str_alloca_ptr(env, parent, ptr, number_of_elements, number_of_elements); - match env.target_info.ptr_width() { + match env.target.ptr_width() { PtrWidth::Bytes4 => { env.builder .new_build_load(zig_str_type(env), alloca, "load_const_str") @@ -1449,7 +1429,7 @@ fn small_str_ptr_width_8<'ctx>( parent: FunctionValue<'ctx>, str_literal: &str, ) -> PointerValue<'ctx> { - debug_assert_eq!(env.target_info.ptr_width() as u8, 8); + debug_assert_eq!(env.target.ptr_width() as u8, 8); let mut array = [0u8; 24]; @@ -1473,7 +1453,7 @@ fn small_str_ptr_width_8<'ctx>( } fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> { - debug_assert_eq!(env.target_info.ptr_width() as u8, 4); + debug_assert_eq!(env.target.ptr_width() as u8, 4); let mut array = [0u8; 12]; @@ -1779,7 +1759,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let refcount_ptr = PointerToRefcount::from_ptr_to_data( env, - if union_layout.stores_tag_id_in_pointer(env.target_info) { + if union_layout.stores_tag_id_in_pointer(env.target) { tag_pointer_clear_tag_id(env, tag_ptr) } else { tag_ptr @@ -1876,7 +1856,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>( let refcount_ptr = PointerToRefcount::from_ptr_to_data( env, - if union_layout.stores_tag_id_in_pointer(env.target_info) { + if union_layout.stores_tag_id_in_pointer(env.target) { tag_pointer_clear_tag_id(env, tag_ptr) } else { tag_ptr @@ -2261,7 +2241,7 @@ fn build_wrapped_tag<'a, 'ctx>( ); let struct_type = env.context.struct_type(&field_types, false); - if union_layout.stores_tag_id_as_data(env.target_info) { + if union_layout.stores_tag_id_as_data(env.target) { let tag_id_ptr = builder.new_build_struct_gep( union_struct_type, raw_data_ptr, @@ -2556,7 +2536,7 @@ fn tag_pointer_set_tag_id<'ctx>( pointer: PointerValue<'ctx>, ) -> PointerValue<'ctx> { // we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3) - debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32); + debug_assert!((tag_id as u32) < env.target.ptr_width() as u32); let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false); @@ -2580,8 +2560,8 @@ fn tag_pointer_set_tag_id<'ctx>( .new_build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr") } -pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) { - match target_info.ptr_width() { +pub fn tag_pointer_tag_id_bits_and_mask(target: Target) -> (u64, u64) { + match target.ptr_width() { roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111), roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011), } @@ -2591,7 +2571,7 @@ pub fn tag_pointer_read_tag_id<'ctx>( env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, ) -> IntValue<'ctx> { - let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); + let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target); let ptr_int = env.ptr_int(); let as_int = env.builder.new_build_ptr_to_int(pointer, ptr_int, "to_int"); @@ -2607,7 +2587,7 @@ pub fn tag_pointer_clear_tag_id<'ctx>( env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, ) -> PointerValue<'ctx> { - let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); + let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target); let as_int = env .builder @@ -2725,7 +2705,7 @@ pub fn get_tag_id<'a, 'ctx>( UnionLayout::Recursive(_) => { let argument_ptr = argument.into_pointer_value(); - if union_layout.stores_tag_id_as_data(env.target_info) { + if union_layout.stores_tag_id_as_data(env.target) { get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr) } else { tag_pointer_read_tag_id(env, argument_ptr) @@ -2756,7 +2736,7 @@ pub fn get_tag_id<'a, 'ctx>( { env.builder.position_at_end(else_block); - let tag_id = if union_layout.stores_tag_id_as_data(env.target_info) { + let tag_id = if union_layout.stores_tag_id_as_data(env.target) { get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr) } else { tag_pointer_read_tag_id(env, argument_ptr) @@ -2894,7 +2874,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>( union_layout: UnionLayout<'a>, fields: &[&[InLayout<'a>]], ) -> PointerValue<'ctx> { - let ptr_bytes = env.target_info; + let ptr_bytes = env.target; let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) { RocUnion::tagged_from_slices(layout_interner, env.context, fields) @@ -2988,11 +2968,11 @@ fn list_literal<'a, 'ctx>( let size = list_length * element_width as usize; let alignment = layout_interner .alignment_bytes(element_layout) - .max(env.target_info.ptr_width() as u32); + .max(env.target.ptr_width() as u32); let mut is_all_constant = true; let zero_elements = - (env.target_info.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize; + (env.target.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize; // runtime-evaluated elements let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena); @@ -3498,7 +3478,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( if value.is_pointer_value() { let clear_tag_id = match other_layout { LayoutRepr::Union(union_layout) => { - union_layout.stores_tag_id_in_pointer(env.target_info) + union_layout.stores_tag_id_in_pointer(env.target) } _ => false, }; @@ -3562,7 +3542,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( let value = value.into_pointer_value(); let clear_tag_id = match layout_interner.runtime_representation(layout) { - LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target_info), + LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target), _ => false, }; @@ -3640,7 +3620,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( if env.mode.runs_expects() { bd.position_at_end(throw_block); - match env.target_info.ptr_width() { + match env.target.ptr_width() { roc_target::PtrWidth::Bytes8 => { let shared_memory = SharedMemoryPointer::get(env); @@ -3712,7 +3692,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>( if env.mode.runs_expects() { bd.position_at_end(throw_block); - match env.target_info.ptr_width() { + match env.target.ptr_width() { roc_target::PtrWidth::Bytes8 => { let shared_memory = SharedMemoryPointer::get(env); @@ -4891,7 +4871,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>( // On x86_*, Modify the argument to specify it is passed by value and nonnull // Aarch*, just passes in the pointer directly. if matches!( - env.target_info.architecture, + env.target.architecture(), roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64 ) { let c_abi_type = match layout_interner.get_repr(*layout) { @@ -5072,7 +5052,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>( } pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> { - let word_type = match env.target_info.ptr_width() { + let word_type = match env.target.ptr_width() { PtrWidth::Bytes4 => env.context.i32_type(), PtrWidth::Bytes8 => env.context.i64_type(), }; @@ -5088,7 +5068,7 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> { // The following three words are available for use in a target-specific manner. // // So, let's create a 5-word buffer. - let size = if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + let size = if env.target.operating_system() == roc_target::OperatingSystem::Windows { // Due to https://github.com/llvm/llvm-project/issues/72908 // on windows, we store the register contents into this buffer directly! 30 @@ -5114,10 +5094,10 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> { pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> { let jmp_buf = get_sjlj_buffer(env); - if env.target_info.architecture == roc_target::Architecture::Aarch64 { + if env.target.architecture() == roc_target::Architecture::Aarch64 { // Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_SETJMP) - } else if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + } else if env.target.operating_system() == roc_target::OperatingSystem::Windows { // Due to https://github.com/llvm/llvm-project/issues/72908, we use a setjmp defined as asm in Zig call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_WINDOWS_SETJMP) } else { @@ -6770,10 +6750,14 @@ pub fn to_cc_return<'a>( layout: InLayout<'a>, ) -> CCReturn { let return_size = layout_interner.stack_size(layout); - let pass_result_by_pointer = match env.target_info.operating_system { - roc_target::OperatingSystem::Windows => return_size > env.target_info.ptr_width() as u32, - roc_target::OperatingSystem::Unix => return_size > 2 * env.target_info.ptr_width() as u32, - roc_target::OperatingSystem::Wasi => return_size > 2 * env.target_info.ptr_width() as u32, + // TODO: loop back and update this. It actually cares about the full abi (arch + os) + let pass_result_by_pointer = match env.target.operating_system() { + roc_target::OperatingSystem::Windows => return_size > env.target.ptr_width() as u32, + roc_target::OperatingSystem::Linux + | roc_target::OperatingSystem::Mac + | roc_target::OperatingSystem::Freestanding => { + return_size > 2 * env.target.ptr_width() as u32 + } }; if return_size == 0 { @@ -6996,7 +6980,7 @@ fn define_global_str_literal_ptr<'ctx>( ptr, &[env .ptr_int() - .const_int(env.target_info.ptr_width() as u64, false)], + .const_int(env.target.ptr_width() as u64, false)], "get_rc_ptr", ) }; @@ -7026,11 +7010,11 @@ fn define_global_str_literal<'ctx>( Some(current) => current, None => { - let size = message.bytes().len() + env.target_info.ptr_width() as usize; + let size = message.bytes().len() + env.target.ptr_width() as usize; let mut bytes = Vec::with_capacity_in(size, env.arena); // insert NULL bytes for the refcount - for _ in 0..env.target_info.ptr_width() as usize { + for _ in 0..env.target.ptr_width() as usize { bytes.push(env.context.i8_type().const_zero()); } @@ -7049,7 +7033,7 @@ fn define_global_str_literal<'ctx>( // strings are NULL-terminated, which means we can't store the refcount (which is 8 // NULL bytes) global.set_constant(true); - global.set_alignment(env.target_info.ptr_width() as u32); + global.set_alignment(env.target.ptr_width() as u32); global.set_unnamed_addr(true); global.set_linkage(inkwell::module::Linkage::Private); diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index c475a17125..3fc6151740 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -378,7 +378,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>( // the list has the same alignment as a usize / ptr. The element comes first in the struct if // its alignment is bigger than that of a list. let element_align = layout_interner.alignment_bytes(element_layout); - let element_first = element_align > env.target_info.ptr_width() as u32; + let element_first = element_align > env.target.ptr_width() as u32; let fields = if element_first { [element_layout, Layout::LIST_U8 /* any list works */] diff --git a/crates/compiler/gen_llvm/src/llvm/convert.rs b/crates/compiler/gen_llvm/src/llvm/convert.rs index 78a02bf460..cfd19b1c2f 100644 --- a/crates/compiler/gen_llvm/src/llvm/convert.rs +++ b/crates/compiler/gen_llvm/src/llvm/convert.rs @@ -11,7 +11,7 @@ use roc_mono::layout::{ round_up_to_alignment, Builtin, FunctionPointer, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, }; -use roc_target::TargetInfo; +use roc_target::Target; use super::struct_::RocStruct; @@ -106,7 +106,7 @@ pub fn struct_type_from_union_layout<'a, 'ctx>( | NullableWrapped { other_tags: tags, .. } => { - if union_layout.stores_tag_id_as_data(env.target_info) { + if union_layout.stores_tag_id_as_data(env.target) { RocUnion::tagged_from_slices(layout_interner, env.context, tags).struct_type() } else { RocUnion::untagged_from_slices(layout_interner, env.context, tags).struct_type() @@ -489,8 +489,8 @@ impl<'ctx> RocUnion<'ctx> { } /// The int type that the C ABI turns our RocList/RocStr into -pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> { - match target_info.ptr_width() { +pub fn str_list_int(ctx: &Context, target: Target) -> IntType<'_> { + match target.ptr_width() { roc_target::PtrWidth::Bytes4 => ctx.i64_type(), roc_target::PtrWidth::Bytes8 => ctx.i128_type(), } diff --git a/crates/compiler/gen_llvm/src/llvm/expect.rs b/crates/compiler/gen_llvm/src/llvm/expect.rs index b1e8b5f9c0..9923531412 100644 --- a/crates/compiler/gen_llvm/src/llvm/expect.rs +++ b/crates/compiler/gen_llvm/src/llvm/expect.rs @@ -184,8 +184,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>( let after_header = offset; let space_for_offsets = env.ptr_int().const_int( - (lookups.len() * env.target_info.ptr_size() + lookups.len() * std::mem::size_of::()) - as _, + (lookups.len() * env.target.ptr_size() + lookups.len() * std::mem::size_of::()) as _, false, ); @@ -232,9 +231,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>( { build_copy(env, original_ptr, offset, lookup_start.into()); - let ptr_width = env - .ptr_int() - .const_int(env.target_info.ptr_size() as _, false); + let ptr_width = env.ptr_int().const_int(env.target.ptr_size() as _, false); offset = env.builder.new_build_int_add(offset, ptr_width, "offset"); } @@ -698,7 +695,7 @@ fn build_clone_tag_help<'a, 'ctx>( let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value()); let layout = LayoutRepr::struct_(field_layouts); - let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) { + let layout = if union_layout.stores_tag_id_in_pointer(env.target) { layout } else { // [...fields, tag ID] @@ -914,7 +911,7 @@ fn write_pointer_with_tag_id<'a, 'ctx>( union_layout: UnionLayout<'a>, tag_id: usize, ) { - if union_layout.stores_tag_id_in_pointer(env.target_info) { + if union_layout.stores_tag_id_in_pointer(env.target) { // first, store tag id as u32 let tag_id_intval = env.context.i32_type().const_int(tag_id as _, false); build_copy(env, ptr, offset, tag_id_intval.into()); diff --git a/crates/compiler/gen_llvm/src/llvm/externs.rs b/crates/compiler/gen_llvm/src/llvm/externs.rs index 7df0e97311..8d091b64ea 100644 --- a/crates/compiler/gen_llvm/src/llvm/externs.rs +++ b/crates/compiler/gen_llvm/src/llvm/externs.rs @@ -195,7 +195,7 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) { } } - match env.target_info.operating_system { + match env.target.operating_system() { roc_target::OperatingSystem::Windows => { // We don't need these functions on Windows } @@ -266,7 +266,7 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) { // write our error message to the RocStr pointer { - let loaded_roc_str = match env.target_info.ptr_width() { + let loaded_roc_str = match env.target.ptr_width() { roc_target::PtrWidth::Bytes4 => roc_str_arg, // On 64-bit we pass RocStrs by reference internally roc_target::PtrWidth::Bytes8 => { @@ -315,12 +315,12 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) { pub fn build_longjmp_call(env: &Env) { let jmp_buf = get_sjlj_buffer(env); - if env.target_info.architecture == roc_target::Architecture::Aarch64 { + if env.target.architecture() == roc_target::Architecture::Aarch64 { // Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig let tag = env.context.i32_type().const_int(1, false); let _call = call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP); - } else if env.target_info.operating_system == roc_target::OperatingSystem::Windows { + } else if env.target.operating_system() == roc_target::OperatingSystem::Windows { let tag = env.context.i32_type().const_int(1, false); let _call = call_void_bitcode_fn( env, diff --git a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs index 4edf5d9f30..2b432950c2 100644 --- a/crates/compiler/gen_llvm/src/llvm/lowlevel.rs +++ b/crates/compiler/gen_llvm/src/llvm/lowlevel.rs @@ -20,7 +20,7 @@ use roc_mono::{ }, list_element_layout, }; -use roc_target::{PtrWidth, TargetInfo}; +use roc_target::{PtrWidth, Target}; use crate::llvm::{ bitcode::{ @@ -129,7 +129,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( // Str.joinWith : List Str, Str -> Str arguments!(list, string); - match env.target_info.ptr_width() { + match env.target.ptr_width() { PtrWidth::Bytes4 => { // list and string are both stored as structs on the stack on 32-bit targets call_str_bitcode_fn( @@ -197,7 +197,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( }; use roc_target::Architecture::*; - let result = match env.target_info.architecture { + let result = match env.target.architecture() { Aarch32 | X86_32 => { let zig_function = env.module.get_function(intrinsic).unwrap(); let zig_function_type = zig_function.get_type(); @@ -283,14 +283,14 @@ pub(crate) fn run_low_level<'a, 'ctx>( }; use roc_target::OperatingSystem::*; - let cc_return_by_pointer = match env.target_info.operating_system { + let cc_return_by_pointer = match env.target.operating_system() { Windows => { // there is just one return register on Windows - (width + 1) as usize > env.target_info.ptr_size() + (width + 1) as usize > env.target.ptr_size() } _ => { // on other systems we have two return registers - (width + 1) as usize > 2 * env.target_info.ptr_size() + (width + 1) as usize > 2 * env.target.ptr_size() } }; @@ -415,7 +415,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( .new_build_alloca(result_type, "alloca_utf8_validate_bytes_result"); use roc_target::Architecture::*; - match env.target_info.architecture { + match env.target.architecture() { Aarch32 | X86_32 => { arguments!(list); let (a, b) = pass_list_or_string_to_zig_32bit(env, list.into_struct_value()); @@ -1299,7 +1299,7 @@ pub(crate) fn run_low_level<'a, 'ctx>( let value_ptr = match layout_interner.runtime_representation(data_layout) { LayoutRepr::Union(union_layout) - if union_layout.stores_tag_id_in_pointer(env.target_info) => + if union_layout.stores_tag_id_in_pointer(env.target) => { tag_pointer_clear_tag_id(env, ptr) } @@ -1898,7 +1898,7 @@ fn dec_split_into_words<'ctx>( fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValueEnum<'ctx> { use roc_target::Architecture::*; use roc_target::OperatingSystem::*; - match env.target_info.operating_system { + match env.target.operating_system() { Windows => { let dec_type = zig_dec_type(env); @@ -1917,8 +1917,8 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu alloca.into() } - Unix => { - if matches!(env.target_info.architecture, X86_32 | X86_64) { + Linux | Mac => { + if matches!(env.target.architecture(), X86_32 | X86_64) { internal_error!("X86 unix does not pass with a dec alloc instead it splits into high and low halves"); } let i64_type = env.context.i64_type(); @@ -1937,21 +1937,15 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu env.builder .new_build_load(i64_type.array_type(2), alloca, "load as array") } - Wasi => unimplemented!(), + Freestanding => unimplemented!(), } } fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> BasicValueEnum<'ctx> { - use roc_target::Architecture::*; - use roc_target::OperatingSystem::*; - let dec = dec.into_int_value(); - match env.target_info { - TargetInfo { - architecture: X86_64 | X86_32, - operating_system: Unix, - } => { + match env.target { + Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { let (low, high) = dec_split_into_words(env, dec); call_str_bitcode_fn( @@ -1962,10 +1956,7 @@ fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> Basic bitcode::DEC_TO_STR, ) } - TargetInfo { - architecture: Wasm32, - operating_system: Unix, - } => call_str_bitcode_fn( + Target::Wasm32 => call_str_bitcode_fn( env, &[], &[dec.into()], @@ -1987,22 +1978,13 @@ fn dec_unary_op<'ctx>( fn_name: &str, dec: BasicValueEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - use roc_target::Architecture::*; - use roc_target::OperatingSystem::*; - let dec = dec.into_int_value(); - match env.target_info { - TargetInfo { - architecture: X86_64 | X86_32, - operating_system: Unix, - } => { + match env.target { + Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { let (low, high) = dec_split_into_words(env, dec); call_bitcode_fn(env, &[low.into(), high.into()], fn_name) } - TargetInfo { - architecture: Wasm32, - operating_system: Unix, - } => call_bitcode_fn(env, &[dec.into()], fn_name), + Target::Wasm32 => call_bitcode_fn(env, &[dec.into()], fn_name), _ => call_bitcode_fn(env, &[dec_alloca(env, dec)], fn_name), } } @@ -2013,17 +1995,11 @@ fn dec_binary_op<'ctx>( dec1: BasicValueEnum<'ctx>, dec2: BasicValueEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - use roc_target::Architecture::*; - use roc_target::OperatingSystem::*; - let dec1 = dec1.into_int_value(); let dec2 = dec2.into_int_value(); - match env.target_info { - TargetInfo { - architecture: X86_64 | X86_32, - operating_system: Unix, - } => { + match env.target { + Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { let (low1, high1) = dec_split_into_words(env, dec1); let (low2, high2) = dec_split_into_words(env, dec2); let lowr_highr = call_bitcode_fn( @@ -2043,10 +2019,7 @@ fn dec_binary_op<'ctx>( .build_load(env.context.i128_type(), ptr, "to_i128") .unwrap() } - TargetInfo { - architecture: Wasm32, - operating_system: Unix, - } => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name), + Target::Wasm32 => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name), _ => call_bitcode_fn( env, &[dec_alloca(env, dec1), dec_alloca(env, dec2)], @@ -2061,20 +2034,14 @@ fn dec_binop_with_overflow<'ctx>( lhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>, ) -> StructValue<'ctx> { - use roc_target::Architecture::*; - use roc_target::OperatingSystem::*; - let lhs = lhs.into_int_value(); let rhs = rhs.into_int_value(); let return_type = zig_with_overflow_roc_dec(env); let return_alloca = env.builder.new_build_alloca(return_type, "return_alloca"); - match env.target_info { - TargetInfo { - architecture: X86_64 | X86_32, - operating_system: Unix, - } => { + match env.target { + Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { let (lhs_low, lhs_high) = dec_split_into_words(env, lhs); let (rhs_low, rhs_high) = dec_split_into_words(env, rhs); call_void_bitcode_fn( @@ -2089,10 +2056,7 @@ fn dec_binop_with_overflow<'ctx>( fn_name, ); } - TargetInfo { - architecture: Wasm32, - operating_system: Unix, - } => { + Target::Wasm32 => { call_void_bitcode_fn( env, &[return_alloca.into(), lhs.into(), rhs.into()], @@ -2123,17 +2087,11 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>( lhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>, ) -> BasicValueEnum<'ctx> { - use roc_target::Architecture::*; - use roc_target::OperatingSystem::*; - let lhs = lhs.into_int_value(); let rhs = rhs.into_int_value(); - match env.target_info { - TargetInfo { - architecture: X86_64 | X86_32, - operating_system: Unix, - } => { + match env.target { + Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => { let (lhs_low, lhs_high) = dec_split_into_words(env, lhs); let (rhs_low, rhs_high) = dec_split_into_words(env, rhs); call_bitcode_fn( @@ -2147,10 +2105,7 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>( fn_name, ) } - TargetInfo { - architecture: Wasm32, - operating_system: Unix, - } => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name), + Target::Wasm32 => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name), _ => call_bitcode_fn(env, &[dec_alloca(env, lhs), dec_alloca(env, rhs)], fn_name), } } @@ -2432,7 +2387,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>( &bitcode::NUM_INT_TO_INT_CHECKING_MAX_AND_MIN[target_int_width][arg_width] }; - let result = match env.target_info.ptr_width() { + let result = match env.target.ptr_width() { PtrWidth::Bytes4 => { let zig_function = env.module.get_function(intrinsic).unwrap(); let zig_function_type = zig_function.get_type(); @@ -2489,12 +2444,11 @@ fn build_int_unary_op<'a, 'ctx, 'env>( } PtrWidth::Bytes8 => { let return_by_pointer = { - if env.target_info.operating_system - == roc_target::OperatingSystem::Windows + if env.target.operating_system() == roc_target::OperatingSystem::Windows { - target_int_width.stack_size() as usize >= env.target_info.ptr_size() + target_int_width.stack_size() as usize >= env.target.ptr_size() } else { - target_int_width.stack_size() as usize > env.target_info.ptr_size() + target_int_width.stack_size() as usize > env.target.ptr_size() } }; if return_by_pointer { diff --git a/crates/compiler/gen_llvm/src/llvm/refcounting.rs b/crates/compiler/gen_llvm/src/llvm/refcounting.rs index 9320d250e9..c22ed07bc5 100644 --- a/crates/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/crates/compiler/gen_llvm/src/llvm/refcounting.rs @@ -80,7 +80,7 @@ impl<'ctx> PointerToRefcount<'ctx> { pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> { let current = self.get_refcount(env); - let one = match env.target_info.ptr_width() { + let one = match env.target.ptr_width() { roc_target::PtrWidth::Bytes4 => { env.context.i32_type().const_int(i32::MIN as u64, false) } @@ -128,7 +128,7 @@ impl<'ctx> PointerToRefcount<'ctx> { ) { let alignment = layout .allocation_alignment_bytes(layout_interner) - .max(env.target_info.ptr_width() as u32); + .max(env.target.ptr_width() as u32); let context = env.context; let block = env.builder.get_insert_block().expect("to be in a function"); @@ -1034,7 +1034,7 @@ pub fn build_header_help<'ctx>( // this should be `Linkage::Private`, but that will remove all of the code for the inc/dec // functions on windows. LLVM just does not emit the assembly for them. Investigate why this is - let linkage = if let roc_target::OperatingSystem::Windows = env.target_info.operating_system { + let linkage = if let roc_target::OperatingSystem::Windows = env.target.operating_system() { Linkage::External } else { Linkage::Private @@ -1162,7 +1162,7 @@ fn build_rec_union_help<'a, 'ctx>( debug_assert!(arg_val.is_pointer_value()); let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val); - let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) { + let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target) { tag_pointer_clear_tag_id(env, arg_val.into_pointer_value()) } else { arg_val.into_pointer_value() diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index 329fb106b9..aa49174d34 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -31,8 +31,7 @@ use crate::layout::{ReturnMethod, WasmLayout}; use crate::low_level::{call_higher_order_lowlevel, LowLevelCall}; use crate::storage::{AddressValue, Storage, StoredValue, StoredVarKind}; use crate::{ - copy_memory, CopyMemoryConfig, Env, DEBUG_SETTINGS, MEMORY_NAME, PTR_SIZE, PTR_TYPE, - TARGET_INFO, + copy_memory, CopyMemoryConfig, Env, DEBUG_SETTINGS, MEMORY_NAME, PTR_SIZE, PTR_TYPE, TARGET, }; #[derive(Clone, Copy, Debug)] @@ -1651,8 +1650,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> { return; } - let stores_tag_id_as_data = union_layout.stores_tag_id_as_data(TARGET_INFO); - let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); + let stores_tag_id_as_data = union_layout.stores_tag_id_as_data(TARGET); + let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET); let (data_size, data_alignment) = union_layout.data_size_and_alignment(self.layout_interner); @@ -1774,7 +1773,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { } }; - if union_layout.stores_tag_id_as_data(TARGET_INFO) { + if union_layout.stores_tag_id_as_data(TARGET) { let id_offset = union_layout.tag_id_offset(self.layout_interner).unwrap(); let id_align = union_layout.discriminant().alignment_bytes(); @@ -1788,7 +1787,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { U0 | U1 | U8 => self.code_builder.i32_load8_u(id_align, id_offset), U16 => self.code_builder.i32_load16_u(id_align, id_offset), } - } else if union_layout.stores_tag_id_in_pointer(TARGET_INFO) { + } else if union_layout.stores_tag_id_in_pointer(TARGET) { self.storage .load_symbols(&mut self.code_builder, &[structure]); self.code_builder.i32_const(3); @@ -1847,7 +1846,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { StoredValue::Local { local_id, .. } => (local_id, 0), }; - let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); + let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET); let from_addr_val = if stores_tag_id_in_pointer { self.code_builder.get_local(tag_local_id); @@ -1912,7 +1911,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { StoredValue::Local { local_id, .. } => (*local_id, 0), }; - let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); + let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET); let from_offset = tag_offset + field_offset; diff --git a/crates/compiler/gen_wasm/src/lib.rs b/crates/compiler/gen_wasm/src/lib.rs index 3cb059f5d1..a450d0fb9b 100644 --- a/crates/compiler/gen_wasm/src/lib.rs +++ b/crates/compiler/gen_wasm/src/lib.rs @@ -18,16 +18,16 @@ use roc_module::symbol::{Interns, ModuleId, Symbol}; use roc_mono::code_gen_help::CodeGenHelp; use roc_mono::ir::{Proc, ProcLayout}; use roc_mono::layout::{LayoutIds, STLayoutInterner}; -use roc_target::TargetInfo; +use roc_target::Target; use roc_wasm_module::parse::ParseError; use roc_wasm_module::{Align, LocalId, ValueType, WasmModule}; use crate::backend::{ProcLookupData, ProcSource, WasmBackend}; use crate::code_builder::CodeBuilder; -const TARGET_INFO: TargetInfo = TargetInfo::default_wasm32(); +const TARGET: Target = Target::Wasm32; const PTR_SIZE: u32 = { - let value = TARGET_INFO.ptr_width() as u32; + let value = TARGET.ptr_width() as u32; // const assert that our pointer width is actually 4 // the code relies on the pointer width being exactly 4 @@ -135,7 +135,7 @@ pub fn build_app_module<'a, 'r>( host_to_app_map, host_module, fn_index_offset, - CodeGenHelp::new(env.arena, TargetInfo::default_wasm32(), env.module_id), + CodeGenHelp::new(env.arena, Target::Wasm32, env.module_id), ); if DEBUG_SETTINGS.user_procs_ir { diff --git a/crates/compiler/load/build.rs b/crates/compiler/load/build.rs index 8a17a04df1..3a5325b4bb 100644 --- a/crates/compiler/load/build.rs +++ b/crates/compiler/load/build.rs @@ -67,7 +67,8 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path: let arena = Bump::new(); let cwd = std::env::current_dir().unwrap(); let source = roc_builtins::roc::module_source(module_id); - let target_info = roc_target::TargetInfo::default_x86_64(); + // This is just for typechecking. Target shouldn't matter. + let target = roc_target::Target::LinuxX64; let function_kind = roc_solve::FunctionKind::LambdaSet; let res_module = roc_load_internal::file::load_and_typecheck_str( @@ -76,7 +77,7 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path: source, cwd, Default::default(), - target_info, + target, function_kind, roc_reporting::report::RenderTarget::ColorTerminal, roc_reporting::report::DEFAULT_PALETTE, diff --git a/crates/compiler/load/src/lib.rs b/crates/compiler/load/src/lib.rs index 58ec0ddfe2..449b37b6a1 100644 --- a/crates/compiler/load/src/lib.rs +++ b/crates/compiler/load/src/lib.rs @@ -6,7 +6,7 @@ use roc_collections::all::MutMap; use roc_module::symbol::ModuleId; use roc_packaging::cache::RocCacheDir; use roc_reporting::report::{Palette, RenderTarget}; -use roc_target::TargetInfo; +use roc_target::Target; use std::path::PathBuf; const SKIP_SUBS_CACHE: bool = { @@ -51,7 +51,7 @@ fn load<'a>( pub fn load_single_threaded<'a>( arena: &'a Bump, load_start: LoadStart<'a>, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, render: RenderTarget, palette: Palette, @@ -65,7 +65,7 @@ pub fn load_single_threaded<'a>( arena, load_start, exposed_types, - target_info, + target, function_kind, cached_subs, render, @@ -172,7 +172,7 @@ pub fn load_and_typecheck_str<'a>( filename: PathBuf, source: &'a str, src_dir: PathBuf, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, render: RenderTarget, roc_cache_dir: RocCacheDir<'_>, @@ -188,7 +188,7 @@ pub fn load_and_typecheck_str<'a>( match load_single_threaded( arena, load_start, - target_info, + target, function_kind, render, palette, diff --git a/crates/compiler/load/tests/test_reporting.rs b/crates/compiler/load/tests/test_reporting.rs index e99485caed..3437042dda 100644 --- a/crates/compiler/load/tests/test_reporting.rs +++ b/crates/compiler/load/tests/test_reporting.rs @@ -123,7 +123,7 @@ mod test_reporting { let mut file = File::create(file_path).unwrap(); writeln!(file, "{module_src}").unwrap(); let load_config = LoadConfig { - target_info: roc_target::TargetInfo::default_x86_64(), + target: roc_target::Target::LinuxX64, render: RenderTarget::Generic, palette: DEFAULT_PALETTE, threading: Threading::Single, diff --git a/crates/compiler/load_internal/src/file.rs b/crates/compiler/load_internal/src/file.rs index 30aa71747d..e38d70c268 100644 --- a/crates/compiler/load_internal/src/file.rs +++ b/crates/compiler/load_internal/src/file.rs @@ -64,7 +64,7 @@ use roc_reporting::report::{to_file_problem_report_string, Palette, RenderTarget use roc_solve::module::{extract_module_owned_implementations, SolveConfig, Solved, SolvedModule}; use roc_solve::FunctionKind; use roc_solve_problem::TypeError; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable}; use roc_types::types::{Alias, Types}; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -104,7 +104,7 @@ macro_rules! log { #[derive(Debug)] pub struct LoadConfig { - pub target_info: TargetInfo, + pub target: Target, pub render: RenderTarget, pub palette: Palette, pub threading: Threading, @@ -453,7 +453,7 @@ fn start_phase<'a>( Subs::default(), None, // no expectations for derived module ProcsBase::default(), - LayoutCache::new(state.layout_interner.fork(), state.target_info), + LayoutCache::new(state.layout_interner.fork(), state.target), ModuleTiming::new(Instant::now()), ) } else if state.make_specializations_pass.current_pass() == 1 { @@ -512,7 +512,7 @@ fn start_phase<'a>( &mut ident_ids, &state.derived_module, &mut module_timing, - state.target_info, + state.target, &state.exposed_types, &mut procs_base, &mut state.world_abilities, @@ -691,7 +691,7 @@ struct State<'a> { pub platform_data: Option>, pub exposed_types: ExposedByModule, pub platform_path: PlatformPath<'a>, - pub target_info: TargetInfo, + pub target: Target, pub(self) function_kind: FunctionKind, /// Note: only packages and platforms actually expose any modules; @@ -755,7 +755,7 @@ impl<'a> State<'a> { root_id: ModuleId, root_path: PathBuf, opt_platform_shorthand: Option<&'a str>, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, exposed_types: ExposedByModule, arc_modules: Arc>>, @@ -776,7 +776,7 @@ impl<'a> State<'a> { root_subs: None, opt_platform_shorthand, cache_dir, - target_info, + target, function_kind, platform_data: None, platform_path: PlatformPath::NotSpecified, @@ -803,7 +803,7 @@ impl<'a> State<'a> { exec_mode, make_specializations_pass: MakeSpecializationsPass::Pass(1), world_abilities: Default::default(), - layout_interner: GlobalLayoutInterner::with_capacity(128, target_info), + layout_interner: GlobalLayoutInterner::with_capacity(128, target), } } } @@ -1033,7 +1033,7 @@ pub fn load_and_typecheck_str<'a>( source: &'a str, src_dir: PathBuf, exposed_types: ExposedByModule, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, render: RenderTarget, palette: Palette, @@ -1049,7 +1049,7 @@ pub fn load_and_typecheck_str<'a>( let cached_subs = MutMap::default(); let load_config = LoadConfig { - target_info, + target, render, palette, threading, @@ -1317,7 +1317,7 @@ pub fn load<'a>( arena, load_start, exposed_types, - load_config.target_info, + load_config.target, load_config.function_kind, cached_types, load_config.render, @@ -1329,7 +1329,7 @@ pub fn load<'a>( arena, load_start, exposed_types, - load_config.target_info, + load_config.target, load_config.function_kind, cached_types, load_config.render, @@ -1346,7 +1346,7 @@ pub fn load_single_threaded<'a>( arena: &'a Bump, load_start: LoadStart<'a>, exposed_types: ExposedByModule, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, cached_types: MutMap, render: RenderTarget, @@ -1376,7 +1376,7 @@ pub fn load_single_threaded<'a>( root_id, root_path, opt_platform_shorthand, - target_info, + target, function_kind, exposed_types, arc_modules, @@ -1427,7 +1427,7 @@ pub fn load_single_threaded<'a>( &msg_tx, &src_dir, roc_cache_dir, - target_info, + target, ); match control_flow { @@ -1672,7 +1672,7 @@ fn load_multi_threaded<'a>( arena: &'a Bump, load_start: LoadStart<'a>, exposed_types: ExposedByModule, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, cached_types: MutMap, render: RenderTarget, @@ -1718,7 +1718,7 @@ fn load_multi_threaded<'a>( root_id, root_path, opt_platform_shorthand, - target_info, + target, function_kind, exposed_types, arc_modules, @@ -1794,7 +1794,7 @@ fn load_multi_threaded<'a>( msg_tx, src_dir, roc_cache_dir, - target_info, + target, ) }); @@ -1923,7 +1923,7 @@ fn worker_task_step<'a>( msg_tx: &MsgSender<'a>, src_dir: &Path, roc_cache_dir: RocCacheDir<'_>, - target_info: TargetInfo, + target: Target, ) -> Result, LoadingProblem<'a>> { match worker_msg_rx.try_recv() { Ok(msg) => { @@ -1952,7 +1952,7 @@ fn worker_task_step<'a>( src_dir, msg_tx.clone(), roc_cache_dir, - target_info, + target, ); match result { @@ -1997,7 +1997,7 @@ fn worker_task<'a>( msg_tx: MsgSender<'a>, src_dir: &Path, roc_cache_dir: RocCacheDir<'_>, - target_info: TargetInfo, + target: Target, ) -> Result<(), LoadingProblem<'a>> { // Keep listening until we receive a Shutdown msg for msg in worker_msg_rx.iter() { @@ -2051,7 +2051,7 @@ fn worker_task<'a>( src_dir, msg_tx.clone(), roc_cache_dir, - target_info, + target, ); match result { @@ -2720,7 +2720,7 @@ fn update<'a>( if state.goal_phase() > Phase::SolveTypes || state.exec_mode.build_if_checks() { let layout_cache = state.layout_caches.pop().unwrap_or_else(|| { - LayoutCache::new(state.layout_interner.fork(), state.target_info) + LayoutCache::new(state.layout_interner.fork(), state.target) }); let typechecked = TypeCheckedModule { @@ -2948,7 +2948,7 @@ fn update<'a>( } let layout_interner = { - let mut taken = GlobalLayoutInterner::with_capacity(0, state.target_info); + let mut taken = GlobalLayoutInterner::with_capacity(0, state.target); std::mem::swap(&mut state.layout_interner, &mut taken); taken }; @@ -3001,7 +3001,7 @@ fn update<'a>( arena, &layout_interner, module_id, - state.target_info, + state.target, ident_ids, &mut update_mode_ids, &mut state.procedures, @@ -5676,7 +5676,7 @@ fn make_specializations<'a>( mut layout_cache: LayoutCache<'a>, specializations_we_must_make: Vec>, mut module_timing: ModuleTiming, - target_info: TargetInfo, + target: Target, world_abilities: WorldAbilities, exposed_by_module: &ExposedByModule, derived_module: SharedDerivedModule, @@ -5691,7 +5691,7 @@ fn make_specializations<'a>( expectation_subs: expectations.as_mut().map(|e| &mut e.subs), home, ident_ids: &mut ident_ids, - target_info, + target, update_mode_ids: &mut update_mode_ids, // call_specialization_counter=0 is reserved call_specialization_counter: 1, @@ -5762,7 +5762,7 @@ fn build_pending_specializations<'a>( declarations: Declarations, mut module_timing: ModuleTiming, mut layout_cache: LayoutCache<'a>, - target_info: TargetInfo, + target: Target, exposed_to_host: ExposedToHost, exposed_by_module: &ExposedByModule, world_abilities: WorldAbilities, @@ -5791,7 +5791,7 @@ fn build_pending_specializations<'a>( expectation_subs: expectations.as_mut().map(|e| &mut e.subs), home, ident_ids: &mut ident_ids, - target_info, + target, update_mode_ids: &mut update_mode_ids, // call_specialization_counter=0 is reserved call_specialization_counter: 1, @@ -6241,7 +6241,7 @@ fn load_derived_partial_procs<'a>( ident_ids: &mut IdentIds, derived_module: &SharedDerivedModule, module_timing: &mut ModuleTiming, - target_info: TargetInfo, + target: Target, exposed_by_module: &ExposedByModule, procs_base: &mut ProcsBase<'a>, world_abilities: &mut WorldAbilities, @@ -6272,7 +6272,7 @@ fn load_derived_partial_procs<'a>( expectation_subs: None, home, ident_ids, - target_info, + target, update_mode_ids: &mut update_mode_ids, // call_specialization_counter=0 is reserved call_specialization_counter: 1, @@ -6346,7 +6346,7 @@ fn run_task<'a>( src_dir: &Path, msg_tx: MsgSender<'a>, roc_cache_dir: RocCacheDir<'_>, - target_info: TargetInfo, + target: Target, ) -> Result<(), LoadingProblem<'a>> { use BuildTask::*; @@ -6451,7 +6451,7 @@ fn run_task<'a>( decls, module_timing, layout_cache, - target_info, + target, exposed_to_host, &exposed_by_module, world_abilities, @@ -6480,7 +6480,7 @@ fn run_task<'a>( layout_cache, specializations_we_must_make, module_timing, - target_info, + target, world_abilities, &exposed_by_module, derived_module, diff --git a/crates/compiler/load_internal/tests/test_load.rs b/crates/compiler/load_internal/tests/test_load.rs index bc1667f18b..b1e9f0af4a 100644 --- a/crates/compiler/load_internal/tests/test_load.rs +++ b/crates/compiler/load_internal/tests/test_load.rs @@ -31,7 +31,7 @@ use roc_reporting::report::RocDocAllocator; use roc_reporting::report::{can_problem, DEFAULT_PALETTE}; use roc_reporting::report::{strip_colors, RenderTarget}; use roc_solve::FunctionKind; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::pretty_print::name_and_print_var; use roc_types::pretty_print::DebugPrint; use std::collections::HashMap; @@ -41,7 +41,7 @@ fn load_and_typecheck( arena: &Bump, filename: PathBuf, exposed_types: ExposedByModule, - target_info: TargetInfo, + target: Target, function_kind: FunctionKind, ) -> Result { use LoadResult::*; @@ -54,7 +54,7 @@ fn load_and_typecheck( DEFAULT_PALETTE, )?; let load_config = LoadConfig { - target_info, + target, function_kind, render: RenderTarget::Generic, palette: DEFAULT_PALETTE, @@ -75,7 +75,7 @@ fn load_and_typecheck( } } -const TARGET_INFO: roc_target::TargetInfo = roc_target::TargetInfo::default_x86_64(); +const TARGET: Target = Target::LinuxX64; // HELPERS @@ -184,7 +184,7 @@ fn multiple_modules_help<'a>( arena, full_file_path, Default::default(), - TARGET_INFO, + TARGET, FunctionKind::LambdaSet, ) }; @@ -204,7 +204,7 @@ fn load_fixture( &arena, filename, subs_by_module, - TARGET_INFO, + TARGET, FunctionKind::LambdaSet, ); let mut loaded_module = match loaded { @@ -367,7 +367,7 @@ fn interface_with_deps() { &arena, filename, subs_by_module, - TARGET_INFO, + TARGET, FunctionKind::LambdaSet, ); diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index f8f76584bc..df7911cbb3 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -3,7 +3,7 @@ use bumpalo::collections::CollectIn; use bumpalo::Bump; use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; -use roc_target::TargetInfo; +use roc_target::Target; use crate::ir::{ BranchInfo, Call, CallSpecId, CallType, Expr, JoinPointId, Literal, ModifyRc, PassedFunction, @@ -93,20 +93,20 @@ pub struct Context<'a> { pub struct CodeGenHelp<'a> { arena: &'a Bump, home: ModuleId, - target_info: TargetInfo, + target: Target, layout_isize: InLayout<'a>, specializations: Vec<'a, Specialization<'a>>, debug_recursion_depth: usize, } impl<'a> CodeGenHelp<'a> { - pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self { - let layout_isize = Layout::isize(target_info); + pub fn new(arena: &'a Bump, target: Target, home: ModuleId) -> Self { + let layout_isize = Layout::isize(target); CodeGenHelp { arena, home, - target_info, + target, layout_isize, specializations: Vec::with_capacity_in(16, arena), debug_recursion_depth: 0, diff --git a/crates/compiler/mono/src/code_gen_help/refcount.rs b/crates/compiler/mono/src/code_gen_help/refcount.rs index d2882732f5..dae9def296 100644 --- a/crates/compiler/mono/src/code_gen_help/refcount.rs +++ b/crates/compiler/mono/src/code_gen_help/refcount.rs @@ -383,7 +383,7 @@ pub fn refcount_reset_proc_body<'a>( }; // Constant for unique refcount - let refcount_1_encoded = match root.target_info.ptr_width() { + let refcount_1_encoded = match root.target.ptr_width() { PtrWidth::Bytes4 => i32::MIN as i128, PtrWidth::Bytes8 => i64::MIN as i128, } @@ -407,7 +407,7 @@ pub fn refcount_reset_proc_body<'a>( ); let mask_lower_bits = match layout_interner.get_repr(layout) { - LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info), + LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target), _ => false, }; @@ -508,7 +508,7 @@ pub fn refcount_resetref_proc_body<'a>( }; // Constant for unique refcount - let refcount_1_encoded = match root.target_info.ptr_width() { + let refcount_1_encoded = match root.target.ptr_width() { PtrWidth::Bytes4 => i32::MIN as i128, PtrWidth::Bytes8 => i64::MIN as i128, } @@ -532,7 +532,7 @@ pub fn refcount_resetref_proc_body<'a>( ); let mask_lower_bits = match layout_interner.get_repr(layout) { - LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info), + LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target), _ => false, }; @@ -617,7 +617,7 @@ fn rc_ptr_from_data_ptr_help<'a>( // Pointer size constant let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size"); let ptr_size_expr = Expr::Literal(Literal::Int( - (root.target_info.ptr_width() as i128).to_ne_bytes(), + (root.target.ptr_width() as i128).to_ne_bytes(), )); let ptr_size_stmt = |next| Stmt::Let(ptr_size_sym, ptr_size_expr, root.layout_isize, next); @@ -630,7 +630,7 @@ fn rc_ptr_from_data_ptr_help<'a>( }, arguments: root.arena.alloc([addr_sym, ptr_size_sym]), }); - let sub_stmt = |next| Stmt::Let(rc_addr_sym, sub_expr, Layout::usize(root.target_info), next); + let sub_stmt = |next| Stmt::Let(rc_addr_sym, sub_expr, Layout::usize(root.target), next); // Typecast the refcount address from integer to pointer let cast_expr = Expr::Call(Call { @@ -697,7 +697,7 @@ fn modify_refcount<'a>( } HelperOp::Dec | HelperOp::DecRef(_) => { - debug_assert!(alignment >= root.target_info.ptr_width() as u32); + debug_assert!(alignment >= root.target.ptr_width() as u32); let (op, ptr) = match ptr { Pointer::ToData(s) => (LowLevel::RefCountDecDataPtr, s), @@ -780,7 +780,7 @@ fn refcount_str<'a>( }; let length_stmt = |next| Stmt::Let(length, length_expr, layout_isize, next); - let alignment = root.target_info.ptr_width() as u32; + let alignment = root.target.ptr_width() as u32; // let is_slice = lowlevel NumLt length zero let is_slice = root.create_symbol(ident_ids, "is_slice"); @@ -1032,7 +1032,7 @@ fn refcount_list<'a>( // let alignment = Ord::max( - root.target_info.ptr_width() as u32, + root.target.ptr_width() as u32, layout_interner.alignment_bytes(elem_layout), ); diff --git a/crates/compiler/mono/src/drop_specialization.rs b/crates/compiler/mono/src/drop_specialization.rs index 3f92d69346..4e510f2b2b 100644 --- a/crates/compiler/mono/src/drop_specialization.rs +++ b/crates/compiler/mono/src/drop_specialization.rs @@ -1181,7 +1181,7 @@ fn specialize_list<'a, 'i>( newer_continuation = arena.alloc(Stmt::Let( index_symbol, Expr::Literal(Literal::Int(i128::to_ne_bytes(i as i128))), - Layout::isize(layout_interner.target_info()), + Layout::isize(layout_interner.target()), index, )); } diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index b1155594c1..a813d43420 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -31,7 +31,7 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_problem::can::{RuntimeError, ShadowKind}; use roc_region::all::{Loc, Region}; use roc_std::RocDec; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::subs::{ instantiate_rigids, storage_copy_var_to, Content, ExhaustiveMark, FlatType, RedundantMark, StorageSubs, Subs, Variable, VariableSubsSlice, @@ -1354,7 +1354,7 @@ pub struct Env<'a, 'i> { pub expectation_subs: Option<&'i mut Subs>, pub home: ModuleId, pub ident_ids: &'i mut IdentIds, - pub target_info: TargetInfo, + pub target: Target, pub update_mode_ids: &'i mut UpdateModeIds, pub call_specialization_counter: u32, // TODO: WorldAbilities and exposed_by_module share things, think about how to combine them diff --git a/crates/compiler/mono/src/ir/decision_tree.rs b/crates/compiler/mono/src/ir/decision_tree.rs index 853011ca09..631e92d677 100644 --- a/crates/compiler/mono/src/ir/decision_tree.rs +++ b/crates/compiler/mono/src/ir/decision_tree.rs @@ -1779,7 +1779,7 @@ fn test_to_comparison<'a>( let real_len = env.unique_symbol(); let test_len = env.unique_symbol(); - let usize_layout = Layout::usize(env.target_info); + let usize_layout = Layout::usize(env.target); stores.push((real_len, usize_layout, real_len_expr)); stores.push((test_len, usize_layout, test_len_expr)); @@ -2337,7 +2337,7 @@ fn decide_to_branching<'a>( let len_symbol = env.unique_symbol(); let switch = Stmt::Switch { - cond_layout: Layout::usize(env.target_info), + cond_layout: Layout::usize(env.target), cond_symbol: len_symbol, branches: branches.into_bump_slice(), default_branch: (default_branch_info, env.arena.alloc(default_branch)), @@ -2355,7 +2355,7 @@ fn decide_to_branching<'a>( Stmt::Let( len_symbol, len_expr, - Layout::usize(env.target_info), + Layout::usize(env.target), env.arena.alloc(switch), ) } else { diff --git a/crates/compiler/mono/src/layout.rs b/crates/compiler/mono/src/layout.rs index d65c608280..ec9009eb65 100644 --- a/crates/compiler/mono/src/layout.rs +++ b/crates/compiler/mono/src/layout.rs @@ -10,7 +10,7 @@ use roc_error_macros::{internal_error, todo_abilities}; use roc_module::ident::{Lowercase, TagName}; use roc_module::symbol::{Interns, Symbol}; use roc_problem::can::RuntimeError; -use roc_target::{PtrWidth, TargetInfo}; +use roc_target::{PtrWidth, Target}; use roc_types::num::NumericRange; use roc_types::subs::{ self, Content, FlatType, GetSubsSlice, OptVariable, RecordFields, Subs, TagExt, TupleElems, @@ -114,7 +114,7 @@ macro_rules! inc_stat { /// Layout cache to avoid recomputing [Layout] from a [Variable] multiple times. #[derive(Debug)] pub struct LayoutCache<'a> { - pub target_info: TargetInfo, + pub target: Target, cache: std::vec::Vec>>, raw_function_cache: std::vec::Vec>>, @@ -128,13 +128,13 @@ pub struct LayoutCache<'a> { } impl<'a> LayoutCache<'a> { - pub fn new(interner: TLLayoutInterner<'a>, target_info: TargetInfo) -> Self { + pub fn new(interner: TLLayoutInterner<'a>, target: Target) -> Self { let mut cache = std::vec::Vec::with_capacity(4); cache.push(Default::default()); let mut raw_cache = std::vec::Vec::with_capacity(4); raw_cache.push(Default::default()); Self { - target_info, + target, cache, raw_function_cache: raw_cache, @@ -964,39 +964,39 @@ impl<'a> UnionLayout<'a> { self.discriminant().layout() } - fn stores_tag_id_in_pointer_bits(tags: &[&[InLayout<'a>]], target_info: TargetInfo) -> bool { - tags.len() < target_info.ptr_width() as usize + fn stores_tag_id_in_pointer_bits(tags: &[&[InLayout<'a>]], target: Target) -> bool { + tags.len() < target.ptr_width() as usize } pub const POINTER_MASK_32BIT: usize = 0b0000_0111; pub const POINTER_MASK_64BIT: usize = 0b0000_0011; - pub fn tag_id_pointer_bits_and_mask(target_info: TargetInfo) -> (usize, usize) { - match target_info.ptr_width() { + pub fn tag_id_pointer_bits_and_mask(target: Target) -> (usize, usize) { + match target.ptr_width() { PtrWidth::Bytes8 => (3, Self::POINTER_MASK_64BIT), PtrWidth::Bytes4 => (2, Self::POINTER_MASK_32BIT), } } // i.e. it is not implicit and not stored in the pointer bits - pub fn stores_tag_id_as_data(&self, target_info: TargetInfo) -> bool { + pub fn stores_tag_id_as_data(&self, target: Target) -> bool { match self { UnionLayout::NonRecursive(_) => true, UnionLayout::Recursive(tags) | UnionLayout::NullableWrapped { other_tags: tags, .. - } => !Self::stores_tag_id_in_pointer_bits(tags, target_info), + } => !Self::stores_tag_id_in_pointer_bits(tags, target), UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableUnwrapped { .. } => false, } } - pub fn stores_tag_id_in_pointer(&self, target_info: TargetInfo) -> bool { + pub fn stores_tag_id_in_pointer(&self, target: Target) -> bool { match self { UnionLayout::NonRecursive(_) => false, UnionLayout::Recursive(tags) | UnionLayout::NullableWrapped { other_tags: tags, .. - } => Self::stores_tag_id_in_pointer_bits(tags, target_info), + } => Self::stores_tag_id_in_pointer_bits(tags, target), UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableUnwrapped { .. } => false, } } @@ -1049,7 +1049,7 @@ impl<'a> UnionLayout<'a> { }; // because we store a refcount, the alignment must be at least the size of a pointer - allocation.max(interner.target_info().ptr_width() as u32) + allocation.max(interner.target().ptr_width() as u32) } /// Size of the data in memory, whether it's stack or heap (for non-null tag ids) @@ -1059,7 +1059,7 @@ impl<'a> UnionLayout<'a> { { let (data_width, data_align) = self.data_size_and_alignment_help_match(interner); - if self.stores_tag_id_as_data(interner.target_info()) { + if self.stores_tag_id_as_data(interner.target()) { use Discriminant::*; match self.discriminant() { U0 => (round_up_to_alignment(data_width, data_align), data_align), @@ -1089,7 +1089,7 @@ impl<'a> UnionLayout<'a> { where I: LayoutInterner<'a>, { - if !self.stores_tag_id_as_data(interner.target_info()) { + if !self.stores_tag_id_as_data(interner.target()) { return None; }; @@ -1151,7 +1151,7 @@ impl<'a> UnionLayout<'a> { UnionLayout::Recursive(_) | UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableWrapped { .. } - | UnionLayout::NullableUnwrapped { .. } => interner.target_info().ptr_width() as u32, + | UnionLayout::NullableUnwrapped { .. } => interner.target().ptr_width() as u32, } } @@ -2686,7 +2686,7 @@ impl<'a> LayoutRepr<'a> { LayoutRepr::Builtin(builtin) => { use Builtin::*; - match interner.target_info().ptr_width() { + match interner.target().ptr_width() { PtrWidth::Bytes4 => { // more things fit into a register false @@ -2700,7 +2700,7 @@ impl<'a> LayoutRepr<'a> { LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true, LayoutRepr::Struct(_) => { // TODO: write tests for this! - self.stack_size(interner) as usize > interner.target_info().max_by_value_size() + self.stack_size(interner) as usize > interner.target().max_by_value_size() } LayoutRepr::LambdaSet(lambda_set) => interner @@ -2739,7 +2739,7 @@ impl<'a> LayoutRepr<'a> { use LayoutRepr::*; match self { - Builtin(builtin) => builtin.stack_size(interner.target_info()), + Builtin(builtin) => builtin.stack_size(interner.target()), Struct(field_layouts) => { let mut sum = 0; @@ -2754,9 +2754,9 @@ impl<'a> LayoutRepr<'a> { .get_repr(lambda_set.runtime_representation()) .stack_size_without_alignment(interner), RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => { - interner.target_info().ptr_width() as u32 + interner.target().ptr_width() as u32 } - Erased(e) => e.stack_size_without_alignment(interner.target_info()), + Erased(e) => e.stack_size_without_alignment(interner.target()), } } @@ -2801,17 +2801,17 @@ impl<'a> LayoutRepr<'a> { Recursive(_) | NullableWrapped { .. } | NullableUnwrapped { .. } - | NonNullableUnwrapped(_) => interner.target_info().ptr_width() as u32, + | NonNullableUnwrapped(_) => interner.target().ptr_width() as u32, } } LambdaSet(lambda_set) => interner .get_repr(lambda_set.runtime_representation()) .alignment_bytes(interner), - Builtin(builtin) => builtin.alignment_bytes(interner.target_info()), + Builtin(builtin) => builtin.alignment_bytes(interner.target()), RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => { - interner.target_info().ptr_width() as u32 + interner.target().ptr_width() as u32 } - Erased(e) => e.alignment_bytes(interner.target_info()), + Erased(e) => e.alignment_bytes(interner.target()), } } @@ -2819,7 +2819,7 @@ impl<'a> LayoutRepr<'a> { where I: LayoutInterner<'a>, { - let ptr_width = interner.target_info().ptr_width() as u32; + let ptr_width = interner.target().ptr_width() as u32; use LayoutRepr::*; match self { @@ -2834,7 +2834,7 @@ impl<'a> LayoutRepr<'a> { } Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner), FunctionPointer(_) => ptr_width, - Erased(e) => e.allocation_alignment_bytes(interner.target_info()), + Erased(e) => e.allocation_alignment_bytes(interner.target()), } } @@ -2994,15 +2994,15 @@ impl<'a> LayoutRepr<'a> { pub type SeenRecPtrs<'a> = VecSet>; impl<'a> Layout<'a> { - pub fn usize(target_info: TargetInfo) -> InLayout<'a> { - match target_info.ptr_width() { + pub fn usize(target: Target) -> InLayout<'a> { + match target.ptr_width() { roc_target::PtrWidth::Bytes4 => Layout::U32, roc_target::PtrWidth::Bytes8 => Layout::U64, } } - pub fn isize(target_info: TargetInfo) -> InLayout<'a> { - match target_info.ptr_width() { + pub fn isize(target: Target) -> InLayout<'a> { + match target.ptr_width() { roc_target::PtrWidth::Bytes4 => Layout::I32, roc_target::PtrWidth::Bytes8 => Layout::I64, } @@ -3067,10 +3067,10 @@ impl<'a> Builtin<'a> { pub const WRAPPER_LEN: u32 = 1; pub const WRAPPER_CAPACITY: u32 = 2; - pub fn stack_size(&self, target_info: TargetInfo) -> u32 { + pub fn stack_size(&self, target: Target) -> u32 { use Builtin::*; - let ptr_width = target_info.ptr_width() as u32; + let ptr_width = target.ptr_width() as u32; match self { Int(int) => int.stack_size(), @@ -3082,20 +3082,20 @@ impl<'a> Builtin<'a> { } } - pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 { + pub fn alignment_bytes(&self, target: Target) -> u32 { use std::mem::align_of; use Builtin::*; - let ptr_width = target_info.ptr_width() as u32; + let ptr_width = target.ptr_width() as u32; // for our data structures, what counts is the alignment of the `( ptr, len )` tuple, and // since both of those are one pointer size, the alignment of that structure is a pointer // size match self { - Int(int_width) => int_width.alignment_bytes(target_info), - Float(float_width) => float_width.alignment_bytes(target_info), + Int(int_width) => int_width.alignment_bytes(target), + Float(float_width) => float_width.alignment_bytes(target), Bool => align_of::() as u32, - Decimal => IntWidth::I128.alignment_bytes(target_info), + Decimal => IntWidth::I128.alignment_bytes(target), // we often treat these as i128 (64-bit systems) // or i64 (32-bit systems). // @@ -3186,8 +3186,8 @@ impl<'a> Builtin<'a> { where I: LayoutInterner<'a>, { - let target_info = interner.target_info(); - let ptr_width = target_info.ptr_width() as u32; + let target = interner.target(); + let ptr_width = target.ptr_width() as u32; let allocation = match self { Builtin::Str => ptr_width, @@ -3196,10 +3196,10 @@ impl<'a> Builtin<'a> { e.alignment_bytes(interner).max(ptr_width) } // The following are usually not heap-allocated, but they might be when inside a Box. - Builtin::Int(int_width) => int_width.alignment_bytes(target_info).max(ptr_width), - Builtin::Float(float_width) => float_width.alignment_bytes(target_info).max(ptr_width), + Builtin::Int(int_width) => int_width.alignment_bytes(target).max(ptr_width), + Builtin::Float(float_width) => float_width.alignment_bytes(target).max(ptr_width), Builtin::Bool => (core::mem::align_of::() as u32).max(ptr_width), - Builtin::Decimal => IntWidth::I128.alignment_bytes(target_info).max(ptr_width), + Builtin::Decimal => IntWidth::I128.alignment_bytes(target).max(ptr_width), }; allocation.max(ptr_width) @@ -4788,7 +4788,7 @@ mod test { #[test] fn width_and_alignment_union_empty_struct() { - let mut interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64()); + let mut interner = STLayoutInterner::with_capacity(4, Target::LinuxX64); let lambda_set = LambdaSet { args: &(&[] as &[InLayout]), @@ -4813,7 +4813,7 @@ mod test { #[test] fn memcpy_size_result_u32_unit() { - let mut interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64()); + let mut interner = STLayoutInterner::with_capacity(4, Target::LinuxX64); let ok_tag = &[interner.insert(Layout { repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)).direct(), @@ -4829,13 +4829,13 @@ mod test { #[test] fn void_stack_size() { - let interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64()); + let interner = STLayoutInterner::with_capacity(4, Target::LinuxX64); assert_eq!(Layout::VOID_NAKED.repr(&interner).stack_size(&interner), 0); } #[test] fn align_u128_in_tag_union() { - let interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64()); + let interner = STLayoutInterner::with_capacity(4, Target::LinuxX64); assert_eq!(interner.alignment_bytes(Layout::U128), 16); } } diff --git a/crates/compiler/mono/src/layout/erased.rs b/crates/compiler/mono/src/layout/erased.rs index 85bcabcd31..e5b5c9c0a4 100644 --- a/crates/compiler/mono/src/layout/erased.rs +++ b/crates/compiler/mono/src/layout/erased.rs @@ -1,4 +1,4 @@ -use roc_target::TargetInfo; +use roc_target::Target; use super::{InLayout, LayoutRepr, UnionLayout}; @@ -27,16 +27,16 @@ impl Erased { false } - pub fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 { - (target_info.ptr_width() as u32) * 3 + pub fn stack_size_without_alignment(&self, target: Target) -> u32 { + (target.ptr_width() as u32) * 3 } - pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 { - target_info.ptr_width() as u32 + pub fn alignment_bytes(&self, target: Target) -> u32 { + target.ptr_width() as u32 } - pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 { - target_info.ptr_width() as u32 + pub fn allocation_alignment_bytes(&self, target: Target) -> u32 { + target.ptr_width() as u32 } pub fn is_refcounted(&self) -> bool { diff --git a/crates/compiler/mono/src/layout/intern.rs b/crates/compiler/mono/src/layout/intern.rs index 9beb0142bb..b86efabe41 100644 --- a/crates/compiler/mono/src/layout/intern.rs +++ b/crates/compiler/mono/src/layout/intern.rs @@ -10,7 +10,7 @@ use parking_lot::{Mutex, RwLock}; use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_collections::{default_hasher, BumpMap}; use roc_module::symbol::Symbol; -use roc_target::TargetInfo; +use roc_target::Target; use crate::layout::LayoutRepr; @@ -208,7 +208,7 @@ pub trait LayoutInterner<'a>: Sized { self.get_repr(a) == self.get_repr(b) } - fn target_info(&self) -> TargetInfo; + fn target(&self) -> Target; fn alignment_bytes(&self, layout: InLayout<'a>) -> u32 { self.get_repr(layout).alignment_bytes(self) @@ -545,7 +545,7 @@ struct GlobalLayoutInternerInner<'a> { map: Mutex, InLayout<'a>>>, normalized_lambda_set_map: Mutex, LambdaSet<'a>>>, vec: RwLock>>, - target_info: TargetInfo, + target: Target, } /// A derivative of a [GlobalLayoutInterner] interner that provides caching desirable for @@ -564,7 +564,7 @@ pub struct TLLayoutInterner<'a> { normalized_lambda_set_map: BumpMap, LambdaSet<'a>>, /// Cache of interned values from the parent for local access. vec: RefCell>>>, - target_info: TargetInfo, + target: Target, } /// A single-threaded interner, with no concurrency properties. @@ -576,7 +576,7 @@ pub struct STLayoutInterner<'a> { map: BumpMap, InLayout<'a>>, normalized_lambda_set_map: BumpMap, LambdaSet<'a>>, vec: Vec>, - target_info: TargetInfo, + target: Target, } /// Interner constructed with an exclusive lock over [GlobalLayoutInterner] @@ -584,7 +584,7 @@ struct LockedGlobalInterner<'a, 'r> { map: &'r mut BumpMap, InLayout<'a>>, normalized_lambda_set_map: &'r mut BumpMap, LambdaSet<'a>>, vec: &'r mut Vec>, - target_info: TargetInfo, + target: Target, } /// Generic hasher for a value, to be used by all interners. @@ -614,8 +614,8 @@ fn make_normalized_lamdba_set<'a>( impl<'a> GlobalLayoutInterner<'a> { /// Creates a new global interner with the given capacity. - pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self { - STLayoutInterner::with_capacity(cap, target_info).into_global() + pub fn with_capacity(cap: usize, target: Target) -> Self { + STLayoutInterner::with_capacity(cap, target).into_global() } /// Creates a derivative [TLLayoutInterner] pointing back to this global interner. @@ -625,7 +625,7 @@ impl<'a> GlobalLayoutInterner<'a> { map: Default::default(), normalized_lambda_set_map: Default::default(), vec: Default::default(), - target_info: self.0.target_info, + target: self.0.target, } } @@ -637,7 +637,7 @@ impl<'a> GlobalLayoutInterner<'a> { map, normalized_lambda_set_map, vec, - target_info, + target, } = match Arc::try_unwrap(self.0) { Ok(inner) => inner, Err(li) => return Err(Self(li)), @@ -649,7 +649,7 @@ impl<'a> GlobalLayoutInterner<'a> { map, normalized_lambda_set_map, vec, - target_info, + target, }) } @@ -703,7 +703,7 @@ impl<'a> GlobalLayoutInterner<'a> { map: &mut map, normalized_lambda_set_map: &mut normalized_lambda_set_map, vec: &mut vec, - target_info: self.0.target_info, + target: self.0.target, }; reify::reify_lambda_set_captures(arena, &mut interner, slot, normalized.set) } else { @@ -765,7 +765,7 @@ impl<'a> GlobalLayoutInterner<'a> { map: &mut map, normalized_lambda_set_map: &mut normalized_lambda_set_map, vec: &mut vec, - target_info: self.0.target_info, + target: self.0.target, }; let full_layout = reify::reify_recursive_layout(arena, &mut interner, slot, normalized); @@ -927,19 +927,19 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> { value } - fn target_info(&self) -> TargetInfo { - self.target_info + fn target(&self) -> Target { + self.target } } impl<'a> STLayoutInterner<'a> { /// Creates a new single threaded interner with the given capacity. - pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self { + pub fn with_capacity(cap: usize, target: Target) -> Self { let mut interner = Self { map: BumpMap::with_capacity_and_hasher(cap, default_hasher()), normalized_lambda_set_map: BumpMap::with_capacity_and_hasher(cap, default_hasher()), vec: Vec::with_capacity(cap), - target_info, + target, }; fill_reserved_layouts(&mut interner); interner @@ -954,13 +954,13 @@ impl<'a> STLayoutInterner<'a> { map, normalized_lambda_set_map, vec, - target_info, + target, } = self; GlobalLayoutInterner(Arc::new(GlobalLayoutInternerInner { map: Mutex::new(map), normalized_lambda_set_map: Mutex::new(normalized_lambda_set_map), vec: RwLock::new(vec), - target_info, + target, })) } @@ -1072,8 +1072,8 @@ macro_rules! st_impl { self.vec[index] } - fn target_info(&self) -> TargetInfo { - self.target_info + fn target(&self) -> Target{ + self.target } } }; @@ -1758,13 +1758,13 @@ pub mod dbg_stable { mod insert_lambda_set { use bumpalo::Bump; use roc_module::symbol::Symbol; - use roc_target::TargetInfo; + use roc_target::Target; use crate::layout::{LambdaSet, Layout, LayoutRepr, SemanticRepr}; use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup}; - const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64(); + const TARGET: Target = Target::LinuxX64; const TEST_SET: &&[(Symbol, &[InLayout])] = &(&[(Symbol::ATTR_ATTR, &[Layout::UNIT] as &[_])] as &[_]); const TEST_ARGS: &&[InLayout] = &(&[Layout::UNIT] as &[_]); @@ -1776,7 +1776,7 @@ mod insert_lambda_set { fn two_threads_write() { for _ in 0..100 { let mut arenas: Vec<_> = std::iter::repeat_with(Bump::new).take(10).collect(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let set = TEST_SET; let repr = Layout::UNIT; std::thread::scope(|s| { @@ -1797,7 +1797,7 @@ mod insert_lambda_set { #[test] fn insert_then_reintern() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut interner = global.fork(); let lambda_set = @@ -1812,7 +1812,7 @@ mod insert_lambda_set { #[test] fn write_global_then_single_threaded() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let set = TEST_SET; let repr = Layout::UNIT; @@ -1832,7 +1832,7 @@ mod insert_lambda_set { #[test] fn write_single_threaded_then_global() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut st_interner = global.unwrap().unwrap(); let set = TEST_SET; @@ -1852,13 +1852,13 @@ mod insert_lambda_set { #[cfg(test)] mod insert_recursive_layout { use bumpalo::Bump; - use roc_target::TargetInfo; + use roc_target::Target; use crate::layout::{Builtin, InLayout, Layout, LayoutRepr, SemanticRepr, UnionLayout}; use super::{GlobalLayoutInterner, LayoutInterner}; - const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64(); + const TARGET: Target = Target::LinuxX64; fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> { let list_rec = Layout { @@ -1905,7 +1905,7 @@ mod insert_recursive_layout { #[test] fn write_two_threads() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let layout = { let mut interner = global.fork(); make_layout(arena, &mut interner) @@ -1927,7 +1927,7 @@ mod insert_recursive_layout { #[test] fn write_twice_thread_local_single_thread() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut interner = global.fork(); let layout = make_layout(arena, &mut interner); @@ -1943,7 +1943,7 @@ mod insert_recursive_layout { #[test] fn write_twice_single_thread() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut interner = GlobalLayoutInterner::unwrap(global).unwrap(); let layout = make_layout(arena, &mut interner); @@ -1960,7 +1960,7 @@ mod insert_recursive_layout { fn many_threads_read_write() { for _ in 0..100 { let mut arenas: Vec<_> = std::iter::repeat_with(Bump::new).take(10).collect(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); std::thread::scope(|s| { let mut handles = Vec::with_capacity(10); for arena in arenas.iter_mut() { @@ -1983,7 +1983,7 @@ mod insert_recursive_layout { #[test] fn insert_then_reintern() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut interner = global.fork(); let layout = make_layout(arena, &mut interner); @@ -1996,7 +1996,7 @@ mod insert_recursive_layout { #[test] fn write_global_then_single_threaded() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let layout = { let mut interner = global.fork(); make_layout(arena, &mut interner) @@ -2018,7 +2018,7 @@ mod insert_recursive_layout { #[test] fn write_single_threaded_then_global() { let arena = &Bump::new(); - let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); + let global = GlobalLayoutInterner::with_capacity(2, TARGET); let mut st_interner = global.unwrap().unwrap(); let layout = make_layout(arena, &mut st_interner); diff --git a/crates/compiler/mono/src/reset_reuse.rs b/crates/compiler/mono/src/reset_reuse.rs index f6a8bd7c52..3ef098148e 100644 --- a/crates/compiler/mono/src/reset_reuse.rs +++ b/crates/compiler/mono/src/reset_reuse.rs @@ -20,7 +20,7 @@ use bumpalo::collections::CollectIn; use roc_collections::{MutMap, MutSet}; use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; -use roc_target::TargetInfo; +use roc_target::Target; /** Insert reset and reuse operations into the IR. @@ -30,7 +30,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( arena: &'a Bump, layout_interner: &'i STLayoutInterner<'a>, home: ModuleId, - target_info: TargetInfo, + target: Target, ident_ids: &'i mut IdentIds, update_mode_ids: &'i mut UpdateModeIds, procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, @@ -44,7 +44,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( let new_proc = insert_reset_reuse_operations_proc( arena, layout_interner, - target_info, + target, home, ident_ids, update_mode_ids, @@ -58,7 +58,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>( fn insert_reset_reuse_operations_proc<'a, 'i>( arena: &'a Bump, layout_interner: &'i STLayoutInterner<'a>, - target_info: TargetInfo, + target: Target, home: ModuleId, ident_ids: &'i mut IdentIds, update_mode_ids: &'i mut UpdateModeIds, @@ -70,7 +70,7 @@ fn insert_reset_reuse_operations_proc<'a, 'i>( } let mut env = ReuseEnvironment { - target_info, + target, symbol_tags: MutMap::default(), non_unique_symbols: MutSet::default(), reuse_tokens: MutMap::default(), @@ -464,7 +464,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( ), ModifyRc::Free(_) => { if union_layout - .stores_tag_id_in_pointer(environment.target_info) + .stores_tag_id_in_pointer(environment.target) { ( Symbol::new(home, ident_ids.gen_unique()), @@ -761,7 +761,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( // Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump. let mut first_pass_body_environment = ReuseEnvironment { - target_info: environment.target_info, + target: environment.target, symbol_tags: environment.symbol_tags.clone(), non_unique_symbols: environment.non_unique_symbols.clone(), reuse_tokens: max_reuse_token_symbols.clone(), @@ -924,7 +924,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>( let (second_pass_body_environment, second_pass_body) = { // Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump. let mut body_environment = ReuseEnvironment { - target_info: environment.target_info, + target: environment.target, symbol_tags: environment.symbol_tags.clone(), non_unique_symbols: environment.non_unique_symbols.clone(), reuse_tokens: used_reuse_tokens.clone(), @@ -1182,7 +1182,7 @@ enum JoinPointReuseTokens<'a> { #[derive(Clone)] struct ReuseEnvironment<'a> { - target_info: TargetInfo, + target: Target, symbol_tags: MutMap, non_unique_symbols: MutSet, reuse_tokens: ReuseTokens<'a>, diff --git a/crates/compiler/roc_target/Cargo.toml b/crates/compiler/roc_target/Cargo.toml index e75e309667..f2357a24e0 100644 --- a/crates/compiler/roc_target/Cargo.toml +++ b/crates/compiler/roc_target/Cargo.toml @@ -8,6 +8,8 @@ license.workspace = true version.workspace = true [dependencies] +roc_error_macros = { path = "../../error_macros" } + strum.workspace = true strum_macros.workspace = true target-lexicon.workspace = true diff --git a/crates/compiler/roc_target/src/lib.rs b/crates/compiler/roc_target/src/lib.rs index 334041b994..927c583ff9 100644 --- a/crates/compiler/roc_target/src/lib.rs +++ b/crates/compiler/roc_target/src/lib.rs @@ -3,70 +3,104 @@ // See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] -use strum_macros::{EnumCount, EnumIter, EnumString, IntoStaticStr}; +use std::str::FromStr; + +use roc_error_macros::user_error; +use strum_macros::{EnumCount, EnumIter}; use target_lexicon::Triple; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum OperatingSystem { + Freestanding, + Linux, + Mac, Windows, - Unix, - Wasi, } -impl OperatingSystem { - pub const fn new(target: target_lexicon::OperatingSystem) -> Option { - match target { - target_lexicon::OperatingSystem::Windows => Some(OperatingSystem::Windows), - target_lexicon::OperatingSystem::Wasi => Some(OperatingSystem::Wasi), - target_lexicon::OperatingSystem::Linux => Some(OperatingSystem::Unix), - target_lexicon::OperatingSystem::MacOSX { .. } => Some(OperatingSystem::Unix), - target_lexicon::OperatingSystem::Darwin => Some(OperatingSystem::Unix), - target_lexicon::OperatingSystem::Unknown => Some(OperatingSystem::Unix), - _ => None, - } - } +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PtrWidth { + Bytes4 = 4, + Bytes8 = 8, +} - pub const fn object_file_ext(&self) -> &str { - match self { - OperatingSystem::Windows => "obj", - OperatingSystem::Unix => "o", - OperatingSystem::Wasi => "wasm", - } - } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter, EnumCount)] +pub enum Architecture { + Aarch32, + Aarch64, + Wasm32, + X86_32, + X86_64, +} - pub const fn static_library_file_ext(&self) -> &str { - match self { - OperatingSystem::Windows => "lib", - OperatingSystem::Unix => "a", - OperatingSystem::Wasi => "wasm", - } - } - - pub const fn executable_file_ext(&self) -> Option<&str> { - match self { - OperatingSystem::Windows => Some("exe"), - OperatingSystem::Unix => None, - OperatingSystem::Wasi => Some("wasm"), - } +impl std::fmt::Display for Architecture { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let arch_str = match self { + Architecture::Aarch32 => "aarch32", + Architecture::Aarch64 => "aarch64", + Architecture::Wasm32 => "wasm32", + Architecture::X86_32 => "x86_32", + Architecture::X86_64 => "x86_64", + }; + write!(f, "{}", arch_str) } } -impl From for OperatingSystem { - fn from(target: target_lexicon::OperatingSystem) -> Self { - Self::new(target) - .unwrap_or_else(|| unreachable!("unsupported operating system {:?}", target)) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct TargetInfo { - pub architecture: Architecture, - pub operating_system: OperatingSystem, -} - -impl TargetInfo { +impl Architecture { pub const fn ptr_width(&self) -> PtrWidth { - self.architecture.ptr_width() + use Architecture::*; + + match self { + X86_64 | Aarch64 => PtrWidth::Bytes8, + X86_32 | Aarch32 | Wasm32 => PtrWidth::Bytes4, + } + } + + pub const fn ptr_alignment_bytes(&self) -> usize { + self.ptr_width() as usize + } +} + +#[derive(Debug, Copy, Clone, EnumIter, PartialEq, Eq)] +pub enum Target { + LinuxX32, + LinuxX64, + LinuxArm64, + MacX64, + MacArm64, + WinX32, + WinX64, + WinArm64, + Wasm32, +} + +impl Target { + pub const fn architecture(&self) -> Architecture { + use Target::*; + match self { + LinuxX32 | WinX32 => Architecture::X86_32, + LinuxX64 | WinX64 | MacX64 => Architecture::X86_64, + LinuxArm64 | WinArm64 | MacArm64 => Architecture::Aarch64, + Wasm32 => Architecture::Wasm32, + } + } + + pub const fn operating_system(&self) -> OperatingSystem { + use Target::*; + match self { + LinuxX32 | LinuxX64 | LinuxArm64 => OperatingSystem::Linux, + MacX64 | MacArm64 => OperatingSystem::Mac, + WinX32 | WinX64 | WinArm64 => OperatingSystem::Windows, + Wasm32 => OperatingSystem::Freestanding, + } + } + + pub const fn arch_os(&self) -> (Architecture, OperatingSystem) { + (self.architecture(), self.operating_system()) + } + + pub const fn ptr_width(&self) -> PtrWidth { + self.architecture().ptr_width() } pub const fn ptr_size(&self) -> usize { @@ -85,196 +119,177 @@ impl TargetInfo { } pub const fn ptr_alignment_bytes(&self) -> usize { - self.architecture.ptr_alignment_bytes() + self.architecture().ptr_alignment_bytes() } - pub const fn default_aarch64() -> Self { - TargetInfo { - architecture: Architecture::Aarch64, - operating_system: OperatingSystem::Unix, - } - } - - pub const fn default_x86_64() -> Self { - TargetInfo { - architecture: Architecture::X86_64, - operating_system: OperatingSystem::Unix, - } - } - - pub const fn default_wasm32() -> Self { - TargetInfo { - architecture: Architecture::Wasm32, - operating_system: OperatingSystem::Wasi, - } - } -} - -impl From<&target_lexicon::Triple> for TargetInfo { - fn from(triple: &target_lexicon::Triple) -> Self { - let architecture = Architecture::from(triple.architecture); - let operating_system = OperatingSystem::from(triple.operating_system); - - Self { - architecture, - operating_system, - } - } -} - -#[repr(u8)] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum PtrWidth { - Bytes4 = 4, - Bytes8 = 8, -} - -/// These should be sorted alphabetically! -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter, EnumCount)] -#[repr(u8)] -pub enum Architecture { - Aarch32, - Aarch64, - Wasm32, - X86_32, - X86_64, -} - -impl Architecture { - pub const fn ptr_width(&self) -> PtrWidth { - use Architecture::*; - + pub const fn object_file_ext(&self) -> &str { + use Target::*; match self { - X86_64 | Aarch64 => PtrWidth::Bytes8, - X86_32 | Aarch32 | Wasm32 => PtrWidth::Bytes4, + LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "o", + WinX32 | WinX64 | WinArm64 => "obj", + Wasm32 => "wasm", } } - pub const fn ptr_alignment_bytes(&self) -> usize { - self.ptr_width() as usize - } -} - -impl From for Architecture { - fn from(target: target_lexicon::Architecture) -> Self { - match target { - target_lexicon::Architecture::X86_64 => Architecture::X86_64, - target_lexicon::Architecture::X86_32(_) => Architecture::X86_32, - target_lexicon::Architecture::Aarch64(_) => Architecture::Aarch64, - target_lexicon::Architecture::Arm(_) => Architecture::Aarch32, - target_lexicon::Architecture::Wasm32 => Architecture::Wasm32, - _ => unreachable!("unsupported architecture"), - } - } -} - -#[derive(Debug, Copy, Clone, EnumIter, EnumString, IntoStaticStr, PartialEq, Eq, Default)] -pub enum Target { - #[strum(serialize = "system")] - #[default] - System, - #[strum(serialize = "linux-x32")] - LinuxX32, - #[strum(serialize = "linux-x64")] - LinuxX64, - #[strum(serialize = "linux-arm64")] - LinuxArm64, - #[strum(serialize = "macos-x64")] - MacX64, - #[strum(serialize = "macos-arm64")] - MacArm64, - #[strum(serialize = "windows-x32")] - WinX32, - #[strum(serialize = "windows-x64")] - WinX64, - #[strum(serialize = "windows-arm64")] - WinArm64, - #[strum(serialize = "wasm32")] - Wasm32, -} - -const MACOS: target_lexicon::OperatingSystem = target_lexicon::OperatingSystem::MacOSX { - major: 12, - minor: 0, - patch: 0, -}; - -impl Target { - pub fn to_triple(self) -> Triple { - use target_lexicon::*; - + pub const fn static_library_file_ext(&self) -> &str { + use Target::*; match self { - Target::System => Triple::host(), - Target::LinuxX32 => Triple { - architecture: Architecture::X86_32(X86_32Architecture::I386), - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Linux, - environment: Environment::Unknown, - binary_format: BinaryFormat::Elf, - }, - Target::LinuxX64 => Triple { - architecture: Architecture::X86_64, - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Linux, - environment: Environment::Unknown, - binary_format: BinaryFormat::Elf, - }, - Target::LinuxArm64 => Triple { - architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64), - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Linux, - environment: Environment::Unknown, - binary_format: BinaryFormat::Elf, - }, - Target::WinX32 => Triple { - architecture: Architecture::X86_32(X86_32Architecture::I386), - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Windows, - environment: Environment::Gnu, - binary_format: BinaryFormat::Coff, - }, - Target::WinX64 => Triple { - architecture: Architecture::X86_64, - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Windows, - environment: Environment::Gnu, - binary_format: BinaryFormat::Coff, - }, - Target::WinArm64 => Triple { - architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64), - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Windows, - environment: Environment::Gnu, - binary_format: BinaryFormat::Coff, - }, - Target::MacX64 => Triple { - architecture: Architecture::X86_64, - vendor: Vendor::Apple, - operating_system: MACOS, - environment: Environment::Unknown, - binary_format: BinaryFormat::Macho, - }, - Target::MacArm64 => Triple { - architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64), - vendor: Vendor::Apple, - operating_system: MACOS, - environment: Environment::Unknown, - binary_format: BinaryFormat::Macho, - }, - Target::Wasm32 => Triple { - architecture: Architecture::Wasm32, - vendor: Vendor::Unknown, - operating_system: OperatingSystem::Wasi, - environment: Environment::Unknown, - binary_format: BinaryFormat::Wasm, - }, + LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "a", + WinX32 | WinX64 | WinArm64 => "lib", + Wasm32 => "wasm", + } + } + + pub const fn executable_file_ext(&self) -> Option<&str> { + use Target::*; + match self { + LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => None, + WinX32 | WinX64 | WinArm64 => Some("exe"), + Wasm32 => Some("wasm"), } } } -impl From<&Target> for Triple { +pub enum ParseError { + InvalidTargetString, +} + +impl FromStr for Target { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + use Target::*; + match s { + "system" => Ok(Self::default()), + "linux-x32" => Ok(LinuxX32), + "linux-x64" => Ok(LinuxX64), + "linux-arm64" => Ok(LinuxArm64), + // TODO: Can we change these to just `mac`. + // Currently, we need to keep it as `macos` to match platform naming. + "macos-x64" => Ok(MacX64), + "macos-arm64" => Ok(MacArm64), + "windows-x32" => Ok(WinX32), + "windows-x64" => Ok(WinX64), + "windows-arm64" => Ok(WinArm64), + "wasm32" => Ok(Wasm32), + _ => Err(ParseError::InvalidTargetString), + } + } +} + +impl From for &'static str { + fn from(target: Target) -> Self { + Self::from(&target) + } +} + +impl From<&Target> for &'static str { fn from(target: &Target) -> Self { - target.to_triple() + use Target::*; + match target { + LinuxX32 => "linux-x32", + LinuxX64 => "linux-x64", + LinuxArm64 => "linux-arm64", + // TODO: Can we change these to just `mac`. + // Currently, we need to keep it as `macos` to match platform naming. + MacX64 => "macos-x64", + MacArm64 => "macos-arm64", + WinX32 => "windows-x32", + WinX64 => "windows-x64", + WinArm64 => "windows-arm64", + Wasm32 => "wasm32", + } + } +} + +impl Default for Target { + fn default() -> Self { + Triple::host().into() + } +} + +impl From<&Triple> for Target { + fn from(triple: &Triple) -> Self { + use target_lexicon::*; + match triple { + Triple { + architecture: Architecture::X86_32(_), + operating_system: OperatingSystem::Linux, + .. + } => Target::LinuxX32, + Triple { + architecture: Architecture::X86_64, + operating_system: OperatingSystem::Linux, + .. + } => Target::LinuxX64, + Triple { + architecture: Architecture::Aarch64(_), + operating_system: OperatingSystem::Linux, + .. + } => Target::LinuxArm64, + Triple { + architecture: Architecture::X86_32(_), + operating_system: OperatingSystem::Windows, + .. + } => Target::WinX32, + Triple { + architecture: Architecture::X86_64, + operating_system: OperatingSystem::Windows, + .. + } => Target::WinX64, + Triple { + architecture: Architecture::Aarch64(_), + operating_system: OperatingSystem::Windows, + .. + } => Target::WinArm64, + Triple { + architecture: Architecture::X86_64, + operating_system: OperatingSystem::MacOSX { .. } | OperatingSystem::Darwin, + .. + } => Target::MacX64, + Triple { + architecture: Architecture::Aarch64(_), + operating_system: OperatingSystem::MacOSX { .. } | OperatingSystem::Darwin, + .. + } => Target::MacArm64, + Triple { + architecture: Architecture::Wasm32, + .. + } => Target::Wasm32, + _ => { + user_error!("Target triple ({}) is not currently supported by the roc compiler. Feel free to file an issue to request support", triple); + } + } + } +} + +impl From for Target { + fn from(triple: Triple) -> Self { + Target::from(&triple) + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum TargetFromTripleError { + TripleUnsupported, +} + +impl TryFrom<(Architecture, OperatingSystem)> for Target { + type Error = TargetFromTripleError; + + fn try_from(arch_os: (Architecture, OperatingSystem)) -> Result { + match arch_os { + (Architecture::X86_32, OperatingSystem::Linux) => Ok(Target::LinuxX32), + (Architecture::X86_64, OperatingSystem::Linux) => Ok(Target::LinuxX64), + (Architecture::Aarch64, OperatingSystem::Linux) => Ok(Target::LinuxArm64), + (Architecture::X86_32, OperatingSystem::Windows) => Ok(Target::WinX32), + (Architecture::X86_64, OperatingSystem::Windows) => Ok(Target::WinX64), + (Architecture::Aarch64, OperatingSystem::Windows) => Ok(Target::WinArm64), + (Architecture::X86_64, OperatingSystem::Mac) => Ok(Target::MacX64), + (Architecture::Aarch64, OperatingSystem::Mac) => Ok(Target::MacArm64), + (Architecture::Wasm32, _) => Ok(Target::Wasm32), + _ => Err(TargetFromTripleError::TripleUnsupported), + } } } @@ -283,48 +298,3 @@ impl std::fmt::Display for Target { write!(f, "{}", Into::<&'static str>::into(self)) } } - -pub fn get_target_triple_str(target: &target_lexicon::Triple) -> Option<&'static str> { - match target { - target_lexicon::Triple { - architecture: target_lexicon::Architecture::Wasm32, - .. - } => Some(Target::Wasm32.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Linux, - architecture: target_lexicon::Architecture::X86_64, - .. - } => Some(Target::LinuxX64.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Linux, - architecture: target_lexicon::Architecture::Aarch64(_), - .. - } => Some(Target::LinuxArm64.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Darwin, - architecture: target_lexicon::Architecture::Aarch64(_), - .. - } => Some(Target::MacArm64.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Darwin, - architecture: target_lexicon::Architecture::X86_64, - .. - } => Some(Target::MacX64.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Windows, - architecture: target_lexicon::Architecture::X86_64, - .. - } => Some(Target::WinX64.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Windows, - architecture: target_lexicon::Architecture::X86_32(_), - .. - } => Some(Target::WinX32.into()), - target_lexicon::Triple { - operating_system: target_lexicon::OperatingSystem::Windows, - architecture: target_lexicon::Architecture::Aarch64(_), - .. - } => Some(Target::WinArm64.into()), - _ => None, - } -} diff --git a/crates/compiler/test_derive/src/util.rs b/crates/compiler/test_derive/src/util.rs index 0f5cacd2e7..bf07a6ab23 100644 --- a/crates/compiler/test_derive/src/util.rs +++ b/crates/compiler/test_derive/src/util.rs @@ -517,7 +517,7 @@ where { let arena = Bump::new(); let (builtin_module, source, path) = module_source_and_path(builtin); - let target_info = roc_target::TargetInfo::default_x86_64(); + let target = roc_target::Target::LinuxX64; let LoadedModule { mut interns, @@ -531,7 +531,7 @@ where source, path.parent().unwrap().to_path_buf(), Default::default(), - target_info, + target, FunctionKind::LambdaSet, roc_reporting::report::RenderTarget::ColorTerminal, roc_reporting::report::DEFAULT_PALETTE, diff --git a/crates/compiler/test_gen/src/gen_tags.rs b/crates/compiler/test_gen/src/gen_tags.rs index 2e32ebe8c8..96922366bc 100644 --- a/crates/compiler/test_gen/src/gen_tags.rs +++ b/crates/compiler/test_gen/src/gen_tags.rs @@ -22,8 +22,8 @@ fn width_and_alignment_u8_u8() { use roc_mono::layout::Layout; use roc_mono::layout::UnionLayout; - let target_info = roc_target::TargetInfo::default_x86_64(); - let interner = STLayoutInterner::with_capacity(4, target_info); + let target = roc_target::Target::LinuxX64; + let interner = STLayoutInterner::with_capacity(4, target); let t = &[Layout::U8] as &[_]; let tt = [t, t]; diff --git a/crates/compiler/test_gen/src/helpers/dev.rs b/crates/compiler/test_gen/src/helpers/dev.rs index fe148d121c..a4962be5cc 100644 --- a/crates/compiler/test_gen/src/helpers/dev.rs +++ b/crates/compiler/test_gen/src/helpers/dev.rs @@ -56,7 +56,7 @@ pub fn helper( } let load_config = LoadConfig { - target_info: roc_target::TargetInfo::default_x86_64(), + target: roc_target::Target::LinuxX64, render: roc_reporting::report::RenderTarget::ColorTerminal, palette: roc_reporting::report::DEFAULT_PALETTE, threading: Threading::Single, @@ -197,14 +197,9 @@ pub fn helper( mode: roc_gen_dev::AssemblyBackendMode::Test, }; - let target = target_lexicon::Triple::host(); - let module_object = roc_gen_dev::build_module( - &env, - &mut interns, - &mut layout_interner, - &target, - procedures, - ); + let target = target_lexicon::Triple::host().into(); + let module_object = + roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures); let module_out = module_object .write() @@ -215,7 +210,7 @@ pub fn helper( roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); let (mut child, dylib_path) = link( - &target, + target, app_o_file.clone(), // Long term we probably want a smarter way to link in zig builtins. // With the current method all methods are kept and it adds about 100k to all outputs. diff --git a/crates/compiler/test_gen/src/helpers/llvm.rs b/crates/compiler/test_gen/src/helpers/llvm.rs index f6d7b9f7a5..feb543f6ec 100644 --- a/crates/compiler/test_gen/src/helpers/llvm.rs +++ b/crates/compiler/test_gen/src/helpers/llvm.rs @@ -16,7 +16,7 @@ use roc_mono::ir::{CrashTag, OptLevel, SingleEntryPoint}; use roc_packaging::cache::RocCacheDir; use roc_region::all::LineInfo; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; -use target_lexicon::Triple; +use roc_target::Target; #[cfg(feature = "gen-llvm-wasm")] use crate::helpers::from_wasm32_memory::FromWasm32Memory; @@ -52,11 +52,9 @@ fn create_llvm_module<'a>( src: &str, config: HelperConfig, context: &'a inkwell::context::Context, - target: &Triple, + target: Target, function_kind: FunctionKind, ) -> (&'static str, String, &'a Module<'a>) { - let target_info = roc_target::TargetInfo::from(target); - let filename = PathBuf::from("Test.roc"); let src_dir = PathBuf::from("fake/test/path"); @@ -72,7 +70,7 @@ fn create_llvm_module<'a>( } let load_config = LoadConfig { - target_info, + target, function_kind, render: RenderTarget::ColorTerminal, palette: DEFAULT_PALETTE, @@ -227,7 +225,7 @@ fn create_llvm_module<'a>( context, interns, module, - target_info, + target, mode: config.mode, // important! we don't want any procedures to get the C calling convention exposed_to_host: MutSet::default(), @@ -332,33 +330,21 @@ pub fn helper<'a>( context: &'a inkwell::context::Context, function_kind: FunctionKind, ) -> (&'static str, String, Library) { - let target = target_lexicon::Triple::host(); + let target = target_lexicon::Triple::host().into(); let (main_fn_name, delayed_errors, module) = - create_llvm_module(arena, src, config, context, &target, function_kind); + create_llvm_module(arena, src, config, context, target, function_kind); if !config.emit_debug_info { module.strip_debug_info(); } - let res_lib = llvm_module_to_dylib(module, &target, config.opt_level); + let res_lib = llvm_module_to_dylib(module, target, config.opt_level); let lib = res_lib.expect("Error loading compiled dylib for test"); (main_fn_name, delayed_errors, lib) } -#[allow(dead_code)] -fn wasm32_target_tripple() -> Triple { - use target_lexicon::{Architecture, BinaryFormat}; - - let mut triple = Triple::unknown(); - - triple.architecture = Architecture::Wasm32; - triple.binary_format = BinaryFormat::Wasm; - - triple -} - #[allow(dead_code)] fn write_final_wasm() -> bool { #[allow(unused_imports)] @@ -383,10 +369,10 @@ fn compile_to_wasm_bytes<'a>( static TEMP_DIR: OnceLock = OnceLock::new(); let temp_dir = TEMP_DIR.get_or_init(|| tempfile::tempdir().unwrap()); - let target = wasm32_target_tripple(); + let target = Target::Wasm32; let (_main_fn_name, _delayed_errors, llvm_module) = - create_llvm_module(arena, src, config, context, &target, function_kind); + create_llvm_module(arena, src, config, context, target, function_kind); let content_hash = crate::helpers::src_hash(src); let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module); diff --git a/crates/compiler/test_gen/src/helpers/wasm.rs b/crates/compiler/test_gen/src/helpers/wasm.rs index af8af43f0d..0f2ec40f73 100644 --- a/crates/compiler/test_gen/src/helpers/wasm.rs +++ b/crates/compiler/test_gen/src/helpers/wasm.rs @@ -88,7 +88,7 @@ fn compile_roc_to_wasm_bytes<'a, T: Wasm32Result>( } let load_config = LoadConfig { - target_info: roc_target::TargetInfo::default_wasm32(), + target: roc_target::Target::Wasm32, render: roc_reporting::report::RenderTarget::ColorTerminal, palette: DEFAULT_PALETTE_HTML, threading: Threading::Single, diff --git a/crates/compiler/test_gen/src/wasm_linking.rs b/crates/compiler/test_gen/src/wasm_linking.rs index d4e3b2f395..5d00f2b6a9 100644 --- a/crates/compiler/test_gen/src/wasm_linking.rs +++ b/crates/compiler/test_gen/src/wasm_linking.rs @@ -2,7 +2,7 @@ use bumpalo::Bump; use roc_gen_wasm::Env; -use roc_target::TargetInfo; +use roc_target::Target; use std::fs; use std::process::Command; @@ -259,7 +259,7 @@ fn test_help( dump_filename: &str, ) { let arena = Bump::new(); - let mut layout_interner = STLayoutInterner::with_capacity(4, TargetInfo::default_wasm32()); + let mut layout_interner = STLayoutInterner::with_capacity(4, Target::Wasm32); let BackendInputs { env, diff --git a/crates/compiler/test_mono/src/tests.rs b/crates/compiler/test_mono/src/tests.rs index 67a21b65ef..736a2710eb 100644 --- a/crates/compiler/test_mono/src/tests.rs +++ b/crates/compiler/test_mono/src/tests.rs @@ -27,7 +27,7 @@ use roc_mono::ir::ProcLayout; use roc_mono::layout::STLayoutInterner; use test_mono_macros::*; -const TARGET_INFO: roc_target::TargetInfo = roc_target::TargetInfo::default_x86_64(); +const TARGET: roc_target::Target = roc_target::Target::LinuxX64; /// Without this, some tests pass in `cargo test --release` but fail without /// the --release flag because they run out of stack space. This increases @@ -104,7 +104,7 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: boo } let load_config = LoadConfig { - target_info: TARGET_INFO, + target: TARGET, // TODO parameterize function_kind: FunctionKind::LambdaSet, threading: Threading::Single, diff --git a/crates/compiler/test_solve_helpers/src/lib.rs b/crates/compiler/test_solve_helpers/src/lib.rs index 7f2256aad6..4b69aa8177 100644 --- a/crates/compiler/test_solve_helpers/src/lib.rs +++ b/crates/compiler/test_solve_helpers/src/lib.rs @@ -79,7 +79,7 @@ pub fn run_load_and_infer<'a>( file_path, module_src, dir.path().to_path_buf(), - roc_target::TargetInfo::default_x86_64(), + roc_target::Target::LinuxX64, function_kind, roc_reporting::report::RenderTarget::Generic, RocCacheDir::Disallowed, diff --git a/crates/compiler/uitest/src/mono.rs b/crates/compiler/uitest/src/mono.rs index f40e76db9b..9920448d28 100644 --- a/crates/compiler/uitest/src/mono.rs +++ b/crates/compiler/uitest/src/mono.rs @@ -43,7 +43,7 @@ pub(crate) fn write_compiled_ir<'a>( let file_path = dir.path().join(filename); let load_config = LoadConfig { - target_info: roc_target::TargetInfo::default_x86_64(), + target: roc_target::Target::LinuxX64, function_kind: compiler_settings.function_kind, threading: Threading::Single, render: roc_reporting::report::RenderTarget::Generic, diff --git a/crates/docs/src/lib.rs b/crates/docs/src/lib.rs index 32c4b942dd..2d9b5dd175 100644 --- a/crates/docs/src/lib.rs +++ b/crates/docs/src/lib.rs @@ -462,7 +462,7 @@ fn render_sidebar<'a, I: Iterator>(modules: I) - pub fn load_module_for_docs(filename: PathBuf) -> LoadedModule { let arena = Bump::new(); let load_config = LoadConfig { - target_info: roc_target::TargetInfo::default_x86_64(), // This is just type-checking for docs, so "target" doesn't matter + target: roc_target::Target::LinuxX64, // This is just type-checking for docs, so "target" doesn't matter function_kind: roc_solve::FunctionKind::LambdaSet, render: roc_reporting::report::RenderTarget::ColorTerminal, palette: roc_reporting::report::DEFAULT_PALETTE, diff --git a/crates/glue/platform/Target.roc b/crates/glue/platform/Target.roc index 3103486974..b4a0588efa 100644 --- a/crates/glue/platform/Target.roc +++ b/crates/glue/platform/Target.roc @@ -16,7 +16,8 @@ Architecture : [ ] OperatingSystem : [ + Freestanding, + Linux, + Mac, Windows, - Unix, - Wasi, ] diff --git a/crates/glue/src/glue.rs b/crates/glue/src/glue.rs index 6dcb093e79..dba63e6245 100644 --- a/crates/glue/src/glue.rs +++ b/crates/glue/src/glue.rs @@ -176,16 +176,18 @@ pub struct Target { #[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)] #[repr(u8)] pub enum OperatingSystem { - Unix = 0, - Wasi = 1, - Windows = 2, + Freestanding = 0, + Linux = 1, + Mac = 2, + Windows = 3, } impl core::fmt::Debug for OperatingSystem { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Unix => f.write_str("OperatingSystem::Unix"), - Self::Wasi => f.write_str("OperatingSystem::Wasi"), + Self::Freestanding => f.write_str("OperatingSystem::Freestanding"), + Self::Linux => f.write_str("OperatingSystem::Linux"), + Self::Mac => f.write_str("OperatingSystem::Mac"), Self::Windows => f.write_str("OperatingSystem::Windows"), } } diff --git a/crates/glue/src/load.rs b/crates/glue/src/load.rs index c91c296303..1d60909173 100644 --- a/crates/glue/src/load.rs +++ b/crates/glue/src/load.rs @@ -17,7 +17,7 @@ use roc_mono::ir::{generate_glue_procs, CrashTag, GlueProc, OptLevel}; use roc_mono::layout::{GlobalLayoutInterner, LayoutCache, LayoutInterner}; use roc_packaging::cache::{self, RocCacheDir}; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; -use roc_target::{Architecture, TargetInfo}; +use roc_target::{Architecture, Target, TargetFromTripleError::TripleUnsupported}; use roc_types::subs::{Subs, Variable}; use std::fs::File; use std::io::{self, ErrorKind, Write}; @@ -41,16 +41,17 @@ pub fn generate( spec_path: &Path, backend: CodeGenBackend, ) -> io::Result { + let target = Triple::host().into(); // TODO: Add verification around the paths. Make sure they heav the correct file extension and what not. match load_types( input_path.to_path_buf(), Threading::AllAvailable, IgnoreErrors::NONE, + target, ) { Ok(types) => { // TODO: we should to modify the app file first before loading it. // Somehow it has to point to the correct platform file which may not exist on the target machine. - let triple = Triple::host(); let code_gen_options = CodeGenOptions { backend, @@ -61,14 +62,14 @@ pub fn generate( }; let load_config = standard_load_config( - &triple, + target, BuildOrdering::BuildIfChecks, Threading::AllAvailable, ); let arena = ManuallyDrop::new(Bump::new()); let link_type = LinkType::Dylib; - let linking_strategy = if roc_linker::supported(link_type, &triple) { + let linking_strategy = if roc_linker::supported(link_type, target) { LinkingStrategy::Surgical } else { LinkingStrategy::Legacy @@ -79,7 +80,7 @@ pub fn generate( let res_binary_path = match tempdir_res { Ok(dylib_dir) => build_file( &arena, - &triple, + target, spec_path.to_path_buf(), code_gen_options, false, @@ -105,12 +106,10 @@ pub fn generate( expect_metadata: _, }) => { // TODO: Should binary_path be update to deal with extensions? - use target_lexicon::OperatingSystem; - let lib_path = match triple.operating_system { + use roc_target::OperatingSystem; + let lib_path = match target.operating_system() { OperatingSystem::Windows => binary_path.with_extension("dll"), - OperatingSystem::Darwin | OperatingSystem::MacOSX { .. } => { - binary_path.with_extension("dylib") - } + OperatingSystem::Mac => binary_path.with_extension("dylib"), _ => binary_path.with_extension("so.1.0"), }; @@ -398,8 +397,8 @@ pub fn load_types( full_file_path: PathBuf, threading: Threading, ignore_errors: IgnoreErrors, + target: Target, ) -> Result, io::Error> { - let target_info = (&Triple::host()).into(); // TODO the function kind may need to be parameterizable. let function_kind = FunctionKind::LambdaSet; let arena = &Bump::new(); @@ -417,7 +416,7 @@ pub fn load_types( full_file_path, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), LoadConfig { - target_info, + target, function_kind, render: RenderTarget::Generic, palette: DEFAULT_PALETTE, @@ -456,18 +455,19 @@ pub fn load_types( exposed_to_host.get(&symbol).copied() }); - let operating_system = target_info.operating_system; + let operating_system = target.operating_system(); let architectures = Architecture::iter(); let mut arch_types = Vec::with_capacity(architectures.len()); for architecture in architectures { let mut interns = interns.clone(); // TODO there may be a way to avoid this. - let target_info = TargetInfo { - architecture, - operating_system, + let target = match Target::try_from((architecture, operating_system)) { + Ok(t) => t, + Err(TripleUnsupported) => continue, }; - let layout_interner = GlobalLayoutInterner::with_capacity(128, target_info); - let mut layout_cache = LayoutCache::new(layout_interner.fork(), target_info); + + let layout_interner = GlobalLayoutInterner::with_capacity(128, target); + let mut layout_cache = LayoutCache::new(layout_interner.fork(), target); let mut glue_procs_by_layout = MutMap::default(); let mut extern_names = MutMap::default(); @@ -528,7 +528,7 @@ pub fn load_types( arena.alloc(interns), glue_procs_by_layout, layout_cache, - target_info, + target, exposed_to_host.clone(), ); diff --git a/crates/glue/src/roc_type/mod.rs b/crates/glue/src/roc_type/mod.rs index 15ed262721..149ed76034 100644 --- a/crates/glue/src/roc_type/mod.rs +++ b/crates/glue/src/roc_type/mod.rs @@ -195,16 +195,18 @@ pub struct Target { #[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)] #[repr(u8)] pub enum OperatingSystem { - Unix = 0, - Wasi = 1, - Windows = 2, + Freestanding = 0, + Linux = 1, + Mac = 2, + Windows = 3, } impl core::fmt::Debug for OperatingSystem { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { - Self::Unix => f.write_str("OperatingSystem::Unix"), - Self::Wasi => f.write_str("OperatingSystem::Wasi"), + Self::Freestanding => f.write_str("OperatingSystem::Freestanding"), + Self::Linux => f.write_str("OperatingSystem::Linux"), + Self::Mac => f.write_str("OperatingSystem::Mac"), Self::Windows => f.write_str("OperatingSystem::Windows"), } } diff --git a/crates/glue/src/types.rs b/crates/glue/src/types.rs index 2a030f4203..bb3d3ac3bb 100644 --- a/crates/glue/src/types.rs +++ b/crates/glue/src/types.rs @@ -20,7 +20,7 @@ use roc_mono::{ InLayout, Layout, LayoutCache, LayoutInterner, LayoutRepr, TLLayoutInterner, UnionLayout, }, }; -use roc_target::{Architecture, OperatingSystem, TargetInfo}; +use roc_target::{Architecture, OperatingSystem, Target}; use roc_types::{ subs::{Content, FlatType, GetSubsSlice, Label, Subs, SubsSlice, UnionLabels, Variable}, types::{AliasKind, RecordField}, @@ -65,13 +65,13 @@ pub struct Types { /// This is important for declaration order in C; we need to output a /// type declaration earlier in the file than where it gets referenced by another type. deps: VecMap>, - target: TargetInfo, + target: Target, } impl Types { const UNIT: TypeId = TypeId(0); - pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self { + pub fn with_capacity(cap: usize, target: Target) -> Self { let mut types = Vec::with_capacity(cap); let mut sizes = Vec::with_capacity(cap); let mut aligns = Vec::with_capacity(cap); @@ -81,7 +81,7 @@ impl Types { aligns.push(1); Self { - target: target_info, + target, types, sizes, aligns, @@ -98,7 +98,7 @@ impl Types { interns: &'a Interns, glue_procs_by_layout: MutMap, &'a [String]>, layout_cache: LayoutCache<'a>, - target: TargetInfo, + target: Target, mut entry_points: MutMap, ) -> Self { let mut types = Self::with_capacity(entry_points.len(), target); @@ -639,7 +639,7 @@ impl Types { } } - pub fn target(&self) -> TargetInfo { + pub fn target(&self) -> Target { self.target } } @@ -905,11 +905,11 @@ impl From<&Option> for roc_type::U1 { } } -impl From for roc_type::Target { - fn from(target: TargetInfo) -> Self { +impl From for roc_type::Target { + fn from(target: Target) -> Self { roc_type::Target { - architecture: target.architecture.into(), - operatingSystem: target.operating_system.into(), + architecture: target.architecture().into(), + operatingSystem: target.operating_system().into(), } } } @@ -928,10 +928,12 @@ impl From for roc_type::Architecture { impl From for roc_type::OperatingSystem { fn from(os: OperatingSystem) -> Self { + // TODO: Update Glue to new OS Tags. match os { OperatingSystem::Windows => roc_type::OperatingSystem::Windows, - OperatingSystem::Unix => roc_type::OperatingSystem::Unix, - OperatingSystem::Wasi => roc_type::OperatingSystem::Wasi, + OperatingSystem::Linux => roc_type::OperatingSystem::Linux, + OperatingSystem::Mac => roc_type::OperatingSystem::Mac, + OperatingSystem::Freestanding => roc_type::OperatingSystem::Freestanding, } } } @@ -1179,7 +1181,7 @@ impl<'a> Env<'a> { interns: &'a Interns, layout_interner: TLLayoutInterner<'a>, glue_procs_by_layout: MutMap, &'a [String]>, - target: TargetInfo, + target: Target, ) -> Self { Env { arena, diff --git a/crates/lang_srv/src/analysis.rs b/crates/lang_srv/src/analysis.rs index 9c498492d8..fc8ce27d10 100644 --- a/crates/lang_srv/src/analysis.rs +++ b/crates/lang_srv/src/analysis.rs @@ -112,7 +112,7 @@ pub(crate) fn global_analysis(doc_info: DocInfo) -> Vec { fi, &doc_info.source, src_dir, - roc_target::TargetInfo::default_x86_64(), + roc_target::Target::LinuxX64, roc_load::FunctionKind::LambdaSet, roc_reporting::report::RenderTarget::Generic, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), diff --git a/crates/linker/src/elf.rs b/crates/linker/src/elf.rs index 37458bdc4d..6250186675 100644 --- a/crates/linker/src/elf.rs +++ b/crates/linker/src/elf.rs @@ -332,8 +332,7 @@ impl<'a> Surgeries<'a> { } /// Constructs a `Metadata` from a host executable binary, and writes it to disk -pub(crate) fn preprocess_elf( - endianness: target_lexicon::Endianness, +pub(crate) fn preprocess_elf_le( host_exe_path: &Path, metadata_path: &Path, preprocessed_path: &Path, @@ -479,47 +478,33 @@ pub(crate) fn preprocess_elf( let text_disassembly_duration = text_disassembly_start.elapsed(); - let scanning_dynamic_deps_duration; - let platform_gen_start; + let scanning_dynamic_deps_start = Instant::now(); - let out_mmap = match endianness { - target_lexicon::Endianness::Little => { - let scanning_dynamic_deps_start = Instant::now(); + let ElfDynamicDeps { + got_app_syms, + got_sections, + app_sym_indices, + dynamic_lib_count, + shared_lib_index, + } = scan_elf_dynamic_deps( + &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, + ); - let ElfDynamicDeps { - got_app_syms, - got_sections, - app_sym_indices, - dynamic_lib_count, - shared_lib_index, - } = scan_elf_dynamic_deps( - &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, - ); + let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); - scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); + let platform_gen_start = Instant::now(); - platform_gen_start = Instant::now(); - - // TODO little endian - gen_elf_le( - exec_data, - &mut md, - preprocessed_path, - &got_app_syms, - &got_sections, - &app_sym_indices, - dynamic_lib_count, - shared_lib_index, - verbose, - ) - } - target_lexicon::Endianness::Big => { - // TODO probably need to make gen_elf a macro to get this - // to work, which is annoying. A parameterized function - // does *not* work. - todo!("Roc does not yet support big-endian ELF hosts!"); - } - }; + let out_mmap = gen_elf_le( + exec_data, + &mut md, + preprocessed_path, + &got_app_syms, + &got_sections, + &app_sym_indices, + dynamic_lib_count, + shared_lib_index, + verbose, + ); let platform_gen_duration = platform_gen_start.elapsed(); @@ -1743,7 +1728,7 @@ mod tests { use crate::preprocessed_host_filename; use indoc::indoc; - use target_lexicon::Triple; + use roc_target::Target; const ELF64_DYNHOST: &[u8] = include_bytes!("../dynhost_benchmarks_elf64") as &[_]; @@ -1778,9 +1763,6 @@ mod tests { fn collect_undefined_symbols_elf() { let object = object::File::parse(ELF64_DYNHOST).unwrap(); - let mut triple = Triple::host(); - triple.binary_format = target_lexicon::BinaryFormat::Elf; - let mut keys: Vec<_> = object .dynamic_symbols() .filter(is_roc_undefined) @@ -1800,7 +1782,7 @@ mod tests { } #[allow(dead_code)] - fn zig_host_app_help(dir: &Path, target: &Triple) { + fn zig_host_app_help(dir: &Path, target: Target) { let host_zig = indoc!( r#" const std = @import("std"); @@ -1885,10 +1867,9 @@ mod tests { panic!("zig build-exe failed"); } - let preprocessed_host_filename = dir.join(preprocessed_host_filename(target).unwrap()); + let preprocessed_host_filename = dir.join(preprocessed_host_filename(target)); - preprocess_elf( - target_lexicon::Endianness::Little, + preprocess_elf_le( &dir.join("host"), &dir.join("metadata"), &preprocessed_host_filename, @@ -1911,12 +1892,10 @@ mod tests { #[cfg(target_os = "linux")] #[test] fn zig_host_app() { - use std::str::FromStr; - let dir = tempfile::tempdir().unwrap(); let dir = dir.path(); - zig_host_app_help(dir, &Triple::from_str("x86_64-unknown-linux-musl").unwrap()); + zig_host_app_help(dir, Target::LinuxX64); let output = std::process::Command::new(dir.join("final")) .current_dir(dir) diff --git a/crates/linker/src/generate_dylib/macho.rs b/crates/linker/src/generate_dylib/macho.rs index b772e0818c..3bb69321f1 100644 --- a/crates/linker/src/generate_dylib/macho.rs +++ b/crates/linker/src/generate_dylib/macho.rs @@ -1,14 +1,14 @@ use object::write; use object::{Architecture, BinaryFormat, Endianness, SymbolFlags, SymbolKind, SymbolScope}; use roc_error_macros::internal_error; +use roc_target::Target; use std::path::Path; use std::process::Command; -use target_lexicon::Triple; // TODO: Eventually do this from scratch and in memory instead of with ld. pub fn create_dylib_macho( custom_names: &[String], - triple: &Triple, + target: Target, ) -> object::read::Result> { let dummy_obj_file = tempfile::Builder::new() .prefix("roc_lib") @@ -19,9 +19,9 @@ pub fn create_dylib_macho( let dummy_lib_file = tmp.path().to_path_buf().with_file_name("libapp.so"); let obj_target = BinaryFormat::MachO; - let obj_arch = match triple.architecture { - target_lexicon::Architecture::X86_64 => Architecture::X86_64, - target_lexicon::Architecture::Aarch64(_) => Architecture::Aarch64, + let obj_arch = match target.architecture() { + roc_target::Architecture::X86_64 => Architecture::X86_64, + roc_target::Architecture::Aarch64 => Architecture::Aarch64, _ => { // We should have verified this via supported() before calling this function unreachable!() diff --git a/crates/linker/src/generate_dylib/mod.rs b/crates/linker/src/generate_dylib/mod.rs index 7374f28b0a..cbe48a4096 100644 --- a/crates/linker/src/generate_dylib/mod.rs +++ b/crates/linker/src/generate_dylib/mod.rs @@ -1,4 +1,4 @@ -use target_lexicon::Triple; +use roc_target::{OperatingSystem, Target}; mod elf64; mod macho; @@ -12,11 +12,11 @@ pub(crate) use elf64::create_dylib_elf64; pub(crate) use pe::APP_DLL; -pub fn generate(target: &Triple, custom_names: &[String]) -> object::read::Result> { - match target.binary_format { - target_lexicon::BinaryFormat::Elf => elf64::create_dylib_elf64(custom_names), - target_lexicon::BinaryFormat::Macho => macho::create_dylib_macho(custom_names, target), - target_lexicon::BinaryFormat::Coff => Ok(pe::synthetic_dll(custom_names)), +pub fn generate(target: Target, custom_names: &[String]) -> object::read::Result> { + match target.operating_system() { + OperatingSystem::Linux => elf64::create_dylib_elf64(custom_names), + OperatingSystem::Mac => macho::create_dylib_macho(custom_names, target), + OperatingSystem::Windows => Ok(pe::synthetic_dll(custom_names)), other => unimplemented!("dylib creation for {:?}", other), } } @@ -26,8 +26,10 @@ mod tests { use super::*; use object::Object; + use target_lexicon::Triple; - fn check_exports(target: &Triple) { + fn check_exports(triple: &Triple) { + let target = triple.into(); let custom_names = ["foo".to_string(), "bar".to_string()]; let bytes = generate(target, &custom_names).unwrap(); @@ -75,16 +77,9 @@ mod tests { #[test] fn check_exports_coff_manual() { - let target = target_lexicon::Triple { - architecture: target_lexicon::Architecture::X86_64, - operating_system: target_lexicon::OperatingSystem::Windows, - binary_format: target_lexicon::BinaryFormat::Coff, - ..target_lexicon::Triple::host() - }; - let custom_names = ["foo".to_string(), "bar".to_string()]; - let bytes = generate(&target, &custom_names).unwrap(); + let bytes = generate(Target::WinX64, &custom_names).unwrap(); let object = object::read::pe::PeFile64::parse(bytes.as_slice()).unwrap(); let exports = { diff --git a/crates/linker/src/lib.rs b/crates/linker/src/lib.rs index 1f1408bd0b..7378c8662f 100644 --- a/crates/linker/src/lib.rs +++ b/crates/linker/src/lib.rs @@ -11,11 +11,10 @@ use roc_module::symbol::Interns; use roc_packaging::cache::RocCacheDir; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; use roc_solve::FunctionKind; -use roc_target::get_target_triple_str; +use roc_target::{Architecture, OperatingSystem, Target}; use std::cmp::Ordering; use std::mem; use std::path::{Path, PathBuf}; -use target_lexicon::Triple; mod elf; mod macho; @@ -31,30 +30,13 @@ pub enum LinkType { None = 2, } -pub fn supported(link_type: LinkType, target: &Triple) -> bool { +pub fn supported(link_type: LinkType, target: Target) -> bool { if let LinkType::Executable = link_type { match target { - Triple { - architecture: target_lexicon::Architecture::X86_64, - operating_system: target_lexicon::OperatingSystem::Linux, - binary_format: target_lexicon::BinaryFormat::Elf, - .. - } => true, - + Target::LinuxX64 => true, + Target::WinX64 => true, // macho support is incomplete - Triple { - operating_system: target_lexicon::OperatingSystem::Darwin, - binary_format: target_lexicon::BinaryFormat::Macho, - .. - } => false, - - Triple { - architecture: target_lexicon::Architecture::X86_64, - operating_system: target_lexicon::OperatingSystem::Windows, - binary_format: target_lexicon::BinaryFormat::Coff, - .. - } => true, - + Target::MacX64 => false, _ => false, } } else { @@ -64,18 +46,16 @@ pub fn supported(link_type: LinkType, target: &Triple) -> bool { pub const PRECOMPILED_HOST_EXT: &str = "rh"; // Short for "roc host" -pub fn preprocessed_host_filename(target: &Triple) -> Option { - roc_target::get_target_triple_str(target).map(|x| format!("{x}.{PRECOMPILED_HOST_EXT}")) +pub fn preprocessed_host_filename(target: Target) -> String { + format!("{target}.{PRECOMPILED_HOST_EXT}") } -fn metadata_file_name(target: &Triple) -> String { - let target_triple_str = get_target_triple_str(target); - - format!("metadata_{}.rm", target_triple_str.unwrap_or("unknown")) +fn metadata_file_name(target: Target) -> String { + format!("metadata_{}.rm", target) } pub fn link_preprocessed_host( - target: &Triple, + target: Target, platform_path: &Path, roc_app_bytes: &[u8], binary_path: &Path, @@ -88,21 +68,20 @@ pub fn link_preprocessed_host( pub fn generate_stub_lib( input_path: &Path, roc_cache_dir: RocCacheDir<'_>, - triple: &Triple, + target: Target, function_kind: FunctionKind, ) -> (PathBuf, PathBuf, Vec) { // Note: this should theoretically just be able to load the host, I think. // Instead, I am loading an entire app because that was simpler and had example code. // If this was expected to stay around for the the long term, we should change it. // But hopefully it will be removable once we have surgical linking on all platforms. - let target_info = triple.into(); let arena = &bumpalo::Bump::new(); let loaded = roc_load::load_and_monomorphize( arena, input_path.to_path_buf(), roc_cache_dir, LoadConfig { - target_info, + target, function_kind, render: RenderTarget::Generic, palette: DEFAULT_PALETTE, @@ -138,14 +117,14 @@ pub fn generate_stub_lib( }; if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point { - let stub_lib = if let target_lexicon::OperatingSystem::Windows = triple.operating_system { + let stub_lib = if target.operating_system() == OperatingSystem::Windows { platform_path.with_file_name("libapp.obj") } else { platform_path.with_file_name("libapp.so") }; let stub_dll_symbols = exposed_symbols.stub_dll_symbols(); - generate_dynamic_lib(triple, &stub_dll_symbols, &stub_lib); + generate_dynamic_lib(target, &stub_dll_symbols, &stub_lib); (platform_path.into(), stub_lib, stub_dll_symbols) } else { unreachable!(); @@ -153,11 +132,11 @@ pub fn generate_stub_lib( } pub fn generate_stub_lib_from_loaded( - target: &Triple, + target: Target, platform_main_roc: &Path, stub_dll_symbols: &[String], ) -> PathBuf { - let stub_lib_path = if let target_lexicon::OperatingSystem::Windows = target.operating_system { + let stub_lib_path = if target.operating_system() == OperatingSystem::Windows { platform_main_roc.with_file_name("libapp.dll") } else { platform_main_roc.with_file_name("libapp.so") @@ -252,7 +231,7 @@ impl ExposedSymbols { } } -fn generate_dynamic_lib(target: &Triple, stub_dll_symbols: &[String], stub_lib_path: &Path) { +fn generate_dynamic_lib(target: Target, stub_dll_symbols: &[String], stub_lib_path: &Path) { if !stub_lib_is_up_to_date(target, stub_lib_path, stub_dll_symbols) { let bytes = crate::generate_dylib::generate(target, stub_dll_symbols) .unwrap_or_else(|e| internal_error!("{e}")); @@ -261,7 +240,7 @@ fn generate_dynamic_lib(target: &Triple, stub_dll_symbols: &[String], stub_lib_p internal_error!("failed to write stub lib to {:?}: {e}", stub_lib_path) } - if let target_lexicon::OperatingSystem::Windows = target.operating_system { + if target.operating_system() == OperatingSystem::Windows { generate_import_library(stub_lib_path, stub_dll_symbols); } } @@ -336,24 +315,22 @@ fn generate_def_file(custom_names: &[String]) -> Result Ok(def_file) } -fn object_matches_target<'a>(target: &Triple, object: &object::File<'a, &'a [u8]>) -> bool { - use target_lexicon::{Architecture as TLA, OperatingSystem as TLO}; - - match target.architecture { - TLA::X86_64 => { +fn object_matches_target<'a>(target: Target, object: &object::File<'a, &'a [u8]>) -> bool { + match target.architecture() { + Architecture::X86_64 => { if object.architecture() != object::Architecture::X86_64 { return false; } - let target_format = match target.operating_system { - TLO::Linux => object::BinaryFormat::Elf, - TLO::Windows => object::BinaryFormat::Pe, + let target_format = match target.operating_system() { + OperatingSystem::Linux => object::BinaryFormat::Elf, + OperatingSystem::Windows => object::BinaryFormat::Pe, _ => todo!("surgical linker does not support target {:?}", target), }; object.format() == target_format } - TLA::Aarch64(_) => object.architecture() == object::Architecture::Aarch64, + Architecture::Aarch64 => object.architecture() == object::Architecture::Aarch64, _ => todo!("surgical linker does not support target {:?}", target), } } @@ -361,7 +338,7 @@ fn object_matches_target<'a>(target: &Triple, object: &object::File<'a, &'a [u8] /// Checks whether the stub `.dll/.so` is up to date, in other words that it exports exactly the /// symbols that it is supposed to export, and is built for the right target. If this is the case, /// we can skip rebuildingthe stub lib. -fn stub_lib_is_up_to_date(target: &Triple, stub_lib_path: &Path, custom_names: &[String]) -> bool { +fn stub_lib_is_up_to_date(target: Target, stub_lib_path: &Path, custom_names: &[String]) -> bool { if !std::path::Path::exists(stub_lib_path) { return false; } @@ -386,14 +363,14 @@ fn stub_lib_is_up_to_date(target: &Triple, stub_lib_path: &Path, custom_names: & } pub fn preprocess_host( - target: &Triple, + target: Target, platform_main_roc: &Path, preprocessed_path: &Path, shared_lib: &Path, stub_dll_symbols: &[String], ) { let metadata_path = platform_main_roc.with_file_name(metadata_file_name(target)); - let host_exe_path = if let target_lexicon::OperatingSystem::Windows = target.operating_system { + let host_exe_path = if target.operating_system() == OperatingSystem::Windows { platform_main_roc.with_file_name("dynhost.exe") } else { platform_main_roc.with_file_name("dynhost") @@ -414,7 +391,7 @@ pub fn preprocess_host( /// Constructs a `Metadata` from a host executable binary, and writes it to disk #[allow(clippy::too_many_arguments)] fn preprocess( - target: &Triple, + target: Target, host_exe_path: &Path, metadata_path: &Path, preprocessed_path: &Path, @@ -427,14 +404,9 @@ fn preprocess( println!("Targeting: {target}"); } - let endianness = target - .endianness() - .unwrap_or(target_lexicon::Endianness::Little); - - match target.binary_format { - target_lexicon::BinaryFormat::Elf => { - crate::elf::preprocess_elf( - endianness, + match target.arch_os() { + (_, OperatingSystem::Linux) => { + crate::elf::preprocess_elf_le( host_exe_path, metadata_path, preprocessed_path, @@ -444,9 +416,8 @@ fn preprocess( ); } - target_lexicon::BinaryFormat::Macho => { - crate::macho::preprocess_macho( - target, + (_, OperatingSystem::Mac) => { + crate::macho::preprocess_macho_le( host_exe_path, metadata_path, preprocessed_path, @@ -456,7 +427,7 @@ fn preprocess( ); } - target_lexicon::BinaryFormat::Coff => { + (_, OperatingSystem::Windows) => { crate::pe::preprocess_windows( host_exe_path, metadata_path, @@ -468,12 +439,9 @@ fn preprocess( .unwrap_or_else(|e| internal_error!("{}", e)); } - target_lexicon::BinaryFormat::Wasm => { + (Architecture::Wasm32, _) => { todo!("Roc does not yet support web assembly hosts!"); } - target_lexicon::BinaryFormat::Unknown => { - internal_error!("Roc does not support unknown host binary formats!"); - } other => { internal_error!( concat!( @@ -492,14 +460,14 @@ fn surgery( executable_path: &Path, verbose: bool, time: bool, - target: &Triple, + target: Target, ) { - match target.binary_format { - target_lexicon::BinaryFormat::Elf => { + match target.arch_os() { + (_, OperatingSystem::Linux) => { crate::elf::surgery_elf(roc_app_bytes, metadata_path, executable_path, verbose, time); } - target_lexicon::BinaryFormat::Macho => { + (_, OperatingSystem::Mac) => { crate::macho::surgery_macho( roc_app_bytes, metadata_path, @@ -509,16 +477,13 @@ fn surgery( ); } - target_lexicon::BinaryFormat::Coff => { + (_, OperatingSystem::Windows) => { crate::pe::surgery_pe(executable_path, metadata_path, roc_app_bytes); } - target_lexicon::BinaryFormat::Wasm => { + (Architecture::Wasm32, _) => { todo!("Roc does not yet support web assembly hosts!"); } - target_lexicon::BinaryFormat::Unknown => { - internal_error!("Roc does not support unknown host binary formats!"); - } other => { internal_error!( concat!( diff --git a/crates/linker/src/macho.rs b/crates/linker/src/macho.rs index ce4e8a24d1..2ce2dbced3 100644 --- a/crates/linker/src/macho.rs +++ b/crates/linker/src/macho.rs @@ -17,7 +17,6 @@ use std::{ path::Path, time::{Duration, Instant}, }; -use target_lexicon::Triple; use crate::{ align_by_constraint, align_to_offset_by_constraint, load_struct_inplace, @@ -322,8 +321,7 @@ impl<'a> Surgeries<'a> { } /// Constructs a `Metadata` from a host executable binary, and writes it to disk -pub(crate) fn preprocess_macho( - target: &Triple, +pub(crate) fn preprocess_macho_le( host_exe_path: &Path, metadata_path: &Path, preprocessed_path: &Path, @@ -544,60 +542,42 @@ pub(crate) fn preprocess_macho( let text_disassembly_duration = text_disassembly_start.elapsed(); - let scanning_dynamic_deps_duration; - let platform_gen_start; + let scanning_dynamic_deps_start = Instant::now(); - let out_mmap = { - match target - .endianness() - .unwrap_or(target_lexicon::Endianness::Little) - { - target_lexicon::Endianness::Little => { - let scanning_dynamic_deps_start = Instant::now(); + // let ElfDynamicDeps { + // got_app_syms, + // got_sections, + // dynamic_lib_count, + // shared_lib_index, + // } = scan_elf_dynamic_deps( + // &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, + // ); - // let ElfDynamicDeps { - // got_app_syms, - // got_sections, - // dynamic_lib_count, - // shared_lib_index, - // } = scan_elf_dynamic_deps( - // &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, - // ); + let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); - scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); + let platform_gen_start = Instant::now(); - platform_gen_start = Instant::now(); - - // TODO little endian - let macho_load_so_offset = match macho_load_so_offset { - Some(offset) => offset, - None => { - internal_error!("Host does not link library `{}`!", shared_lib.display()); - } - }; - - // TODO this is correct on modern Macs (they align to the page size) - // but maybe someone can override the alignment somehow? Maybe in the - // future this could change? Is there some way to make this more future-proof? - md.load_align_constraint = 4096; - - gen_macho_le( - exec_data, - &mut md, - preprocessed_path, - macho_load_so_offset, - target, - verbose, - ) - } - target_lexicon::Endianness::Big => { - // TODO Is big-endian macOS even a thing that exists anymore? - // Just ancient PowerPC machines maybe? - todo!("Roc does not yet support big-endian macOS hosts!"); - } + // TODO little endian + let macho_load_so_offset = match macho_load_so_offset { + Some(offset) => offset, + None => { + internal_error!("Host does not link library `{}`!", shared_lib.display()); } }; + // TODO this is correct on modern Macs (they align to the page size) + // but maybe someone can override the alignment somehow? Maybe in the + // future this could change? Is there some way to make this more future-proof? + md.load_align_constraint = 4096; + + let out_mmap = gen_macho_le( + exec_data, + &mut md, + preprocessed_path, + macho_load_so_offset, + verbose, + ); + let platform_gen_duration = platform_gen_start.elapsed(); if verbose { @@ -652,7 +632,6 @@ fn gen_macho_le( md: &mut Metadata, out_filename: &Path, macho_load_so_offset: usize, - _target: &Triple, _verbose: bool, ) -> MmapMut { // Just adding some extra context/useful info here. diff --git a/crates/linker/src/pe.rs b/crates/linker/src/pe.rs index 711c5b7491..fb3176fc85 100644 --- a/crates/linker/src/pe.rs +++ b/crates/linker/src/pe.rs @@ -1795,7 +1795,7 @@ mod test { } let preprocessed_host_filename = - dir.join(preprocessed_host_filename(&Triple::host()).unwrap()); + dir.join(preprocessed_host_filename(Triple::host().into())); preprocess_windows( &dir.join("host.exe"), diff --git a/crates/repl_cli/src/cli_gen.rs b/crates/repl_cli/src/cli_gen.rs index f6170467b9..89e8687dd4 100644 --- a/crates/repl_cli/src/cli_gen.rs +++ b/crates/repl_cli/src/cli_gen.rs @@ -15,18 +15,16 @@ use roc_repl_eval::eval::jit_to_ast; use roc_repl_eval::gen::{format_answer, ReplOutput}; use roc_repl_eval::{ReplApp, ReplAppMemory}; use roc_std::RocStr; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::pretty_print::{name_and_print_var, DebugPrint}; use roc_types::subs::Subs; -use target_lexicon::Triple; pub fn eval_llvm( mut loaded: MonomorphizedModule<'_>, - target: &Triple, + target: Target, opt_level: OptLevel, ) -> Option { let arena = Bump::new(); - let target_info = TargetInfo::from(target); debug_assert_eq!(loaded.exposed_to_host.top_level_values.len(), 1); let (main_fn_symbol, main_fn_var) = loaded @@ -81,7 +79,7 @@ pub fn eval_llvm( &subs, &interns, layout_interner.into_global().fork(), - target_info, + target, ); let expr_str = format_answer(&arena, expr).to_string(); @@ -180,12 +178,10 @@ impl ReplAppMemory for CliMemory { )] fn mono_module_to_dylib_llvm<'a>( arena: &'a Bump, - target: &Triple, + target: Target, loaded: MonomorphizedModule<'a>, opt_level: OptLevel, ) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> { - let target_info = TargetInfo::from(target); - let MonomorphizedModule { procedures, host_exposed_lambda_sets, @@ -217,7 +213,7 @@ fn mono_module_to_dylib_llvm<'a>( context: &context, interns, module, - target_info, + target, mode: LlvmBackendMode::GenTest, // so roc_panic is generated // important! we don't want any procedures to get the C calling convention exposed_to_host: MutSet::default(), @@ -286,7 +282,7 @@ fn mono_module_to_dylib_llvm<'a>( )] fn mono_module_to_dylib_asm<'a>( arena: &'a Bump, - target: &Triple, + target: Target, loaded: MonomorphizedModule<'a>, _opt_level: OptLevel, ) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> { @@ -295,8 +291,6 @@ fn mono_module_to_dylib_asm<'a>( let app_o_file = dir.path().join("app.o"); - let _target_info = TargetInfo::from(target); - let MonomorphizedModule { module_id, procedures, @@ -317,14 +311,8 @@ fn mono_module_to_dylib_asm<'a>( mode: roc_gen_dev::AssemblyBackendMode::Repl, }; - let target = target_lexicon::Triple::host(); - let module_object = roc_gen_dev::build_module( - &env, - &mut interns, - &mut layout_interner, - &target, - procedures, - ); + let module_object = + roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures); let module_out = module_object .write() @@ -342,7 +330,7 @@ fn mono_module_to_dylib_asm<'a>( roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); let (mut child, dylib_path) = roc_build::link::link( - &target, + target, app_o_file.clone(), // Long term we probably want a smarter way to link in zig builtins. // With the current method all methods are kept and it adds about 100k to all outputs. diff --git a/crates/repl_cli/src/lib.rs b/crates/repl_cli/src/lib.rs index 28fed740ac..a340a13369 100644 --- a/crates/repl_cli/src/lib.rs +++ b/crates/repl_cli/src/lib.rs @@ -10,7 +10,7 @@ use roc_repl_ui::colors::{CYAN, END_COL}; use roc_repl_ui::repl_state::{ReplAction, ReplState}; use roc_repl_ui::{format_output, is_incomplete, CONT_PROMPT, PROMPT, SHORT_INSTRUCTIONS, TIPS}; use roc_reporting::report::{ANSI_STYLE_CODES, DEFAULT_PALETTE}; -use roc_target::TargetInfo; +use roc_target::Target; use rustyline::highlight::{Highlighter, PromptInfo}; use rustyline::validate::{self, ValidationContext, ValidationResult, Validator}; use rustyline_derive::{Completer, Helper, Hinter}; @@ -46,8 +46,7 @@ pub fn main() -> i32 { let mut editor = Editor::::new(); let repl_helper = ReplHelper::default(); editor.set_helper(Some(repl_helper)); - let target = Triple::host(); - let target_info = TargetInfo::from(&target); + let target = Triple::host().into(); let mut arena = Bump::new(); loop { @@ -63,9 +62,9 @@ pub fn main() -> i32 { .state; arena.reset(); - match repl_state.step(&arena, line, target_info, DEFAULT_PALETTE) { + match repl_state.step(&arena, line, target, DEFAULT_PALETTE) { ReplAction::Eval { opt_mono, problems } => { - let output = evaluate(opt_mono, problems, &target); + let output = evaluate(opt_mono, problems, target); // If there was no output, don't print a blank line! // (This happens for something like a type annotation.) if !output.is_empty() { @@ -104,7 +103,7 @@ pub fn main() -> i32 { pub fn evaluate( opt_mono: Option>, problems: Problems, - target: &Triple, + target: Target, ) -> String { let opt_output = opt_mono.and_then(|mono| eval_llvm(mono, target, OptLevel::Normal)); format_output(ANSI_STYLE_CODES, opt_output, problems) diff --git a/crates/repl_eval/src/eval.rs b/crates/repl_eval/src/eval.rs index 18468c994d..79964cc538 100644 --- a/crates/repl_eval/src/eval.rs +++ b/crates/repl_eval/src/eval.rs @@ -16,7 +16,7 @@ use roc_mono::layout::{ use roc_parse::ast::{AssignedField, Collection, Expr, Pattern, StrLiteral}; use roc_region::all::{Loc, Region}; use roc_std::RocDec; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::subs::{ Content, FlatType, GetSubsSlice, RecordFields, Subs, TagExt, TupleElems, UnionTags, Variable, }; @@ -26,7 +26,7 @@ use crate::{ReplApp, ReplAppMemory}; struct Env<'a, 'env> { arena: &'a Bump, subs: &'env Subs, - target_info: TargetInfo, + target: Target, interns: &'a Interns, layout_cache: LayoutCache<'a>, } @@ -49,14 +49,14 @@ pub fn jit_to_ast<'a, A: ReplApp<'a>>( subs: &Subs, interns: &'a Interns, layout_interner: TLLayoutInterner<'a>, - target_info: TargetInfo, + target: Target, ) -> Expr<'a> { let mut env = Env { arena, subs, - target_info, + target, interns, - layout_cache: LayoutCache::new(layout_interner, target_info), + layout_cache: LayoutCache::new(layout_interner, target), }; match layout { @@ -338,7 +338,7 @@ fn tag_id_from_recursive_ptr<'a, M: ReplAppMemory>( union_layout: UnionLayout<'a>, rec_addr: usize, ) -> (i64, usize) { - let tag_in_ptr = union_layout.stores_tag_id_in_pointer(env.target_info); + let tag_in_ptr = union_layout.stores_tag_id_in_pointer(env.target); if tag_in_ptr { let (tag_id, data_addr) = mem.deref_pointer_with_tag_id(rec_addr); @@ -416,7 +416,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>( Expr::Str(StrLiteral::PlainLine(arena_str)) }; - match app.call_function_returns_roc_str(env.target_info, main_fn_name, body) { + match app.call_function_returns_roc_str(env.target, main_fn_name, body) { Some(string) => string, None => Expr::REPL_RUNTIME_CRASH, } @@ -628,8 +628,8 @@ fn addr_to_ast<'a, M: ReplAppMemory>( } (_, LayoutRepr::Builtin(Builtin::List(elem_layout))) => { let elem_addr = mem.deref_usize(addr); - let len = mem.deref_usize(addr + env.target_info.ptr_width() as usize); - let _cap = mem.deref_usize(addr + 2 * env.target_info.ptr_width() as usize); + let len = mem.deref_usize(addr + env.target.ptr_width() as usize); + let _cap = mem.deref_usize(addr + 2 * env.target.ptr_width() as usize); list_to_ast(env, mem, elem_addr, len, elem_layout, raw_content) } diff --git a/crates/repl_eval/src/gen.rs b/crates/repl_eval/src/gen.rs index 8aec07a5f3..8fbf00fe92 100644 --- a/crates/repl_eval/src/gen.rs +++ b/crates/repl_eval/src/gen.rs @@ -12,7 +12,7 @@ use roc_parse::ast::Expr; use roc_region::all::LineInfo; use roc_reporting::report::{can_problem, type_problem, RocDocAllocator}; use roc_solve::FunctionKind; -use roc_target::TargetInfo; +use roc_target::Target; #[derive(Debug)] pub struct ReplOutput { @@ -49,7 +49,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator>( arena: &'a Bump, defs: I, expr: &str, - target_info: TargetInfo, + target: Target, palette: Palette, ) -> (Option>, Problems) { let filename = PathBuf::from("replfile.roc"); @@ -62,7 +62,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator>( src_dir, RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), LoadConfig { - target_info, + target, function_kind: FunctionKind::LambdaSet, render: roc_reporting::report::RenderTarget::ColorTerminal, palette, diff --git a/crates/repl_eval/src/lib.rs b/crates/repl_eval/src/lib.rs index e7643ba30b..803311a2e4 100644 --- a/crates/repl_eval/src/lib.rs +++ b/crates/repl_eval/src/lib.rs @@ -1,7 +1,7 @@ //! Provides the functionality for the REPL to evaluate Roc expressions. use roc_parse::ast::Expr; use roc_std::RocDec; -use roc_target::TargetInfo; +use roc_target::Target; pub mod eval; pub mod gen; @@ -28,7 +28,7 @@ pub trait ReplApp<'a> { /// When the executed code calls roc_panic, this function will return None fn call_function_returns_roc_str( &mut self, - target_info: TargetInfo, + target: Target, main_fn_name: &str, transform: F, ) -> Option @@ -36,7 +36,7 @@ pub trait ReplApp<'a> { F: Fn(&'a Self::Memory, usize) -> T, Self::Memory: 'a, { - let roc_str_width = match target_info.ptr_width() { + let roc_str_width = match target.ptr_width() { roc_target::PtrWidth::Bytes4 => 12, roc_target::PtrWidth::Bytes8 => 24, }; diff --git a/crates/repl_expect/src/app.rs b/crates/repl_expect/src/app.rs index d7f2085c0a..5917822375 100644 --- a/crates/repl_expect/src/app.rs +++ b/crates/repl_expect/src/app.rs @@ -1,7 +1,7 @@ use roc_parse::ast::Expr; use roc_repl_eval::{ReplApp, ReplAppMemory}; use roc_std::RocStr; -use roc_target::TargetInfo; +use roc_target::Target; pub(crate) struct ExpectMemory { pub(crate) start: *const u8, @@ -118,7 +118,7 @@ impl<'a> ReplApp<'a> for ExpectReplApp<'a> { fn call_function_returns_roc_str( &mut self, - _target_info: TargetInfo, + _target: Target, main_fn_name: &str, transform: F, ) -> Option diff --git a/crates/repl_expect/src/lib.rs b/crates/repl_expect/src/lib.rs index 3dfc3c4787..95fa587985 100644 --- a/crates/repl_expect/src/lib.rs +++ b/crates/repl_expect/src/lib.rs @@ -8,7 +8,7 @@ use { }, roc_parse::ast::Expr, roc_repl_eval::{eval::jit_to_ast, ReplAppMemory}, - roc_target::TargetInfo, + roc_target::Target, roc_types::subs::{Subs, Variable}, }; @@ -23,7 +23,7 @@ use app::{ExpectMemory, ExpectReplApp}; #[cfg(not(windows))] #[allow(clippy::too_many_arguments)] pub fn get_values<'a>( - target_info: TargetInfo, + target: Target, arena: &'a bumpalo::Bump, subs: &Subs, interns: &'a Interns, @@ -58,7 +58,7 @@ pub fn get_values<'a>( app.offset = start; // TODO: pass layout_cache to jit_to_ast directly - let mut layout_cache = LayoutCache::new(layout_interner.fork(), target_info); + let mut layout_cache = LayoutCache::new(layout_interner.fork(), target); let layout = layout_cache.from_var(arena, variable, subs).unwrap(); let proc_layout = ProcLayout { @@ -76,7 +76,7 @@ pub fn get_values<'a>( subs, interns, layout_interner.fork(), - target_info, + target, ); app.offset += layout_cache.interner.stack_size_and_alignment(layout).0 as usize; @@ -102,17 +102,13 @@ mod test { use crate::run::expect_mono_module_to_dylib; - use super::*; - fn run_expect_test(source: &str, expected: &str) { let arena = bumpalo::Bump::new(); let arena = &arena; - let triple = Triple::host(); - let target = &triple; + let target = Triple::host().into(); let opt_level = roc_mono::ir::OptLevel::Normal; - let target_info = TargetInfo::from(target); let function_kind = FunctionKind::LambdaSet; // Step 1: compile the app and generate the .o file @@ -122,7 +118,7 @@ mod test { std::fs::write(&filename, source).unwrap(); let load_config = LoadConfig { - target_info, + target, function_kind, render: RenderTarget::ColorTerminal, palette: DEFAULT_PALETTE, @@ -150,14 +146,9 @@ mod test { let interns = loaded.interns.clone(); - let (dy_lib, expects_by_module, layout_interner) = expect_mono_module_to_dylib( - arena, - target.clone(), - loaded, - opt_level, - LlvmBackendMode::CliTest, - ) - .unwrap(); + let (dy_lib, expects_by_module, layout_interner) = + expect_mono_module_to_dylib(arena, target, loaded, opt_level, LlvmBackendMode::CliTest) + .unwrap(); let arena = &bumpalo::Bump::new(); let interns = arena.alloc(interns); diff --git a/crates/repl_expect/src/run.rs b/crates/repl_expect/src/run.rs index 47f14a4bcf..aa8b0afdd2 100644 --- a/crates/repl_expect/src/run.rs +++ b/crates/repl_expect/src/run.rs @@ -26,9 +26,8 @@ use roc_mono::{ }; use roc_region::all::Region; use roc_reporting::{error::expect::Renderer, report::RenderTarget}; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::subs::Subs; -use target_lexicon::Triple; pub struct ExpectMemory<'a> { ptr: *mut u8, @@ -469,7 +468,7 @@ fn render_expect_failure<'a>( offset: usize, ) -> std::io::Result { // we always run programs as the host - let target_info = (&target_lexicon::Triple::host()).into(); + let target = target_lexicon::Triple::host().into(); let frame = ExpectFrame::at_offset(start, offset); let module_id = frame.module_id; @@ -487,7 +486,7 @@ fn render_expect_failure<'a>( let symbols = split_expect_lookups(&data.subs, current); let (offset, expressions, variables) = crate::get_values( - target_info, + target, arena, &data.subs, interns, @@ -613,7 +612,7 @@ pub struct ExpectFunctions<'a> { pub fn expect_mono_module_to_dylib<'a>( arena: &'a Bump, - target: Triple, + target: Target, loaded: MonomorphizedModule<'a>, opt_level: OptLevel, mode: LlvmBackendMode, @@ -625,8 +624,6 @@ pub fn expect_mono_module_to_dylib<'a>( ), libloading::Error, > { - let target_info = TargetInfo::from(&target); - let MonomorphizedModule { toplevel_expects, procedures, @@ -638,7 +635,7 @@ pub fn expect_mono_module_to_dylib<'a>( let context = Context::create(); let builder = context.create_builder(); let module = arena.alloc(roc_gen_llvm::llvm::build::module_from_builtins( - &target, &context, "", + target, &context, "", )); let module = arena.alloc(module); @@ -656,7 +653,7 @@ pub fn expect_mono_module_to_dylib<'a>( context: &context, interns, module, - target_info, + target, mode, // important! we don't want any procedures to get the C calling convention exposed_to_host: MutSet::default(), @@ -753,6 +750,6 @@ pub fn expect_mono_module_to_dylib<'a>( env.module.print_to_file(path).unwrap(); } - llvm_module_to_dylib(env.module, &target, opt_level) + llvm_module_to_dylib(env.module, target, opt_level) .map(|dy_lib| (dy_lib, modules_expects, layout_interner)) } diff --git a/crates/repl_test/src/state.rs b/crates/repl_test/src/state.rs index a987b46c38..96a4af523e 100644 --- a/crates/repl_test/src/state.rs +++ b/crates/repl_test/src/state.rs @@ -4,7 +4,6 @@ use roc_repl_cli::{evaluate, ReplHelper}; use roc_repl_ui::is_incomplete; use roc_repl_ui::repl_state::{ReplAction, ReplState}; use roc_reporting::report::DEFAULT_PALETTE; -use roc_target::TargetInfo; use rustyline::Editor; use target_lexicon::Triple; @@ -128,9 +127,8 @@ fn partial_record_definition() { fn tips() { assert!(!is_incomplete("")); let arena = Bump::new(); - let target = Triple::host(); - let target_info = TargetInfo::from(&target); - let action = ReplState::default().step(&arena, "", target_info, DEFAULT_PALETTE); + let target = Triple::host().into(); + let action = ReplState::default().step(&arena, "", target, DEFAULT_PALETTE); assert!(matches!(action, ReplAction::Help)); } @@ -142,9 +140,8 @@ fn standalone_annotation() { incomplete(&mut input); assert!(!is_incomplete(&input)); let arena = Bump::new(); - let target = Triple::host(); - let target_info = TargetInfo::from(&target); - let action = state.step(&arena, &input, target_info, DEFAULT_PALETTE); + let target = Triple::host().into(); + let action = state.step(&arena, &input, target, DEFAULT_PALETTE); assert!(matches!(action, ReplAction::Nothing)); } @@ -153,16 +150,15 @@ fn standalone_annotation() { fn complete(input: &str, state: &mut ReplState, expected_start: &str) { assert!(!is_incomplete(input)); let arena = Bump::new(); - let target = Triple::host(); - let target_info = TargetInfo::from(&target); - let action = state.step(&arena, input, target_info, DEFAULT_PALETTE); + let target = Triple::host().into(); + let action = state.step(&arena, input, target, DEFAULT_PALETTE); let repl_helper = ReplHelper::default(); let mut editor = Editor::::new(); editor.set_helper(Some(repl_helper)); match action { ReplAction::Eval { opt_mono, problems } => { - let string = evaluate(opt_mono, problems, &target); + let string = evaluate(opt_mono, problems, target); let escaped = std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap()) .unwrap(); @@ -190,16 +186,15 @@ fn incomplete(input: &mut String) { fn error(input: &str, state: &mut ReplState, expected_step_result: String) { assert!(!is_incomplete(input)); let arena = Bump::new(); - let target = Triple::host(); - let target_info = TargetInfo::from(&target); - let action = state.step(&arena, input, target_info, DEFAULT_PALETTE); + let target = Triple::host().into(); + let action = state.step(&arena, input, target, DEFAULT_PALETTE); let repl_helper = ReplHelper::default(); let mut editor = Editor::::new(); editor.set_helper(Some(repl_helper)); match action { ReplAction::Eval { opt_mono, problems } => { - let string = evaluate(opt_mono, problems, &target); + let string = evaluate(opt_mono, problems, target); let escaped = std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap()) .unwrap(); diff --git a/crates/repl_ui/src/repl_state.rs b/crates/repl_ui/src/repl_state.rs index 6f2e7103f6..b3c6826a9d 100644 --- a/crates/repl_ui/src/repl_state.rs +++ b/crates/repl_ui/src/repl_state.rs @@ -11,7 +11,7 @@ use roc_parse::{join_alias_to_body, join_ann_to_body}; use roc_region::all::Loc; use roc_repl_eval::gen::{compile_to_mono, Problems}; use roc_reporting::report::Palette; -use roc_target::TargetInfo; +use roc_target::Target; #[derive(Debug, Clone, PartialEq)] struct PastDef { @@ -54,7 +54,7 @@ impl ReplState { &mut self, arena: &'a Bump, line: &str, - target_info: TargetInfo, + target: Target, palette: Palette, ) -> ReplAction<'a> { let pending_past_def; @@ -170,7 +170,7 @@ impl ReplState { arena, self.past_defs.iter().map(|def| def.src.as_str()), src, - target_info, + target, palette, ); diff --git a/crates/repl_wasm/src/repl.rs b/crates/repl_wasm/src/repl.rs index cb6b6822e1..8614ee4b58 100644 --- a/crates/repl_wasm/src/repl.rs +++ b/crates/repl_wasm/src/repl.rs @@ -16,7 +16,7 @@ use roc_repl_ui::{ repl_state::{ReplAction, ReplState}, TIPS, }; -use roc_target::TargetInfo; +use roc_target::Target; use roc_types::pretty_print::{name_and_print_var, DebugPrint}; use crate::{js_create_app, js_get_result_and_memory, js_run_app}; @@ -189,12 +189,12 @@ pub async fn entrypoint_from_js(src: String) -> String { let arena = &Bump::new(); // Compile the app - let target_info = TargetInfo::default_wasm32(); + let target = Target::Wasm32; // Advance the REPL state machine let action = REPL_STATE.with(|repl_state_cell| { let mut repl_state = repl_state_cell.borrow_mut(); - repl_state.step(arena, &src, target_info, DEFAULT_PALETTE_HTML) + repl_state.step(arena, &src, target, DEFAULT_PALETTE_HTML) }); // Perform the action the state machine asked for, and return the appropriate output string @@ -206,7 +206,7 @@ pub async fn entrypoint_from_js(src: String) -> String { ReplAction::Nothing => String::new(), ReplAction::Eval { opt_mono, problems } => { let opt_output = match opt_mono { - Some(mono) => eval_wasm(arena, target_info, mono).await, + Some(mono) => eval_wasm(arena, target, mono).await, None => None, }; @@ -217,7 +217,7 @@ pub async fn entrypoint_from_js(src: String) -> String { async fn eval_wasm<'a>( arena: &'a Bump, - target_info: TargetInfo, + target: Target, mono: MonomorphizedModule<'a>, ) -> Option { let MonomorphizedModule { @@ -311,7 +311,7 @@ async fn eval_wasm<'a>( &subs, &interns, layout_interner.into_global().fork(), - target_info, + target, ); // Transform the Expr to a string diff --git a/crates/valgrind/src/lib.rs b/crates/valgrind/src/lib.rs index 00efead061..5bff7e6059 100644 --- a/crates/valgrind/src/lib.rs +++ b/crates/valgrind/src/lib.rs @@ -14,11 +14,11 @@ fn build_host() { roc_command_utils::root_dir().join("crates/valgrind/zig-platform/main.roc"); // tests always run on the host - let target = target_lexicon::Triple::host(); + let target = target_lexicon::Triple::host().into(); // the preprocessed host is stored beside the platform's main.roc let preprocessed_host_path = - platform_main_roc.with_file_name(preprocessed_host_filename(&target).unwrap()); + platform_main_roc.with_file_name(preprocessed_host_filename(target)); // valgrind does not support avx512 yet: https://bugs.kde.org/show_bug.cgi?id=383010 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -28,7 +28,7 @@ fn build_host() { build_and_preprocess_host( roc_mono::ir::OptLevel::Normal, - &target, + target, &platform_main_roc, &preprocessed_host_path, roc_linker::ExposedSymbols {