Merge pull request #6610 from roc-lang/roc-target

Use roc_target over target_lexicon
This commit is contained in:
Brendan Hansknecht 2024-03-31 18:45:27 -07:00 committed by GitHub
commit c72b95de97
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
73 changed files with 1009 additions and 1372 deletions

1
Cargo.lock generated
View file

@ -3168,6 +3168,7 @@ dependencies = [
name = "roc_target" name = "roc_target"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"roc_error_macros",
"strum", "strum",
"strum_macros", "strum_macros",
"target-lexicon", "target-lexicon",

View file

@ -23,7 +23,7 @@ use roc_mono::ir::OptLevel;
use roc_packaging::cache::RocCacheDir; use roc_packaging::cache::RocCacheDir;
use roc_packaging::tarball::Compression; use roc_packaging::tarball::Compression;
use roc_reporting::report::ANSI_STYLE_CODES; use roc_reporting::report::ANSI_STYLE_CODES;
use roc_target::Target; use roc_target::{Architecture, Target};
use std::env; use std::env;
use std::ffi::{CString, OsStr, OsString}; use std::ffi::{CString, OsStr, OsString};
use std::io; use std::io;
@ -33,7 +33,6 @@ use std::path::{Path, PathBuf};
use std::process; use std::process;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use target_lexicon::{Architecture, Triple};
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
use tempfile::TempDir; use tempfile::TempDir;
@ -442,7 +441,7 @@ fn opt_level_from_flags(matches: &ArgMatches) -> OptLevel {
} }
#[cfg(windows)] #[cfg(windows)]
pub fn test(_matches: &ArgMatches, _triple: Triple) -> io::Result<i32> { pub fn test(_matches: &ArgMatches, _target: Target) -> io::Result<i32> {
todo!("running tests does not work on windows right now") todo!("running tests does not work on windows right now")
} }
@ -454,11 +453,10 @@ struct ModuleTestResults {
} }
#[cfg(not(windows))] #[cfg(not(windows))]
pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> { pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
use roc_build::program::report_problems_monomorphized; use roc_build::program::report_problems_monomorphized;
use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError}; use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError};
use roc_packaging::cache; use roc_packaging::cache;
use roc_target::TargetInfo;
let start_time = Instant::now(); let start_time = Instant::now();
let arena = Bump::new(); let arena = Bump::new();
@ -495,14 +493,12 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
} }
let arena = &arena; let arena = &arena;
let target = &triple;
let target_info = TargetInfo::from(target);
// TODO may need to determine this dynamically based on dev builds. // TODO may need to determine this dynamically based on dev builds.
let function_kind = FunctionKind::LambdaSet; let function_kind = FunctionKind::LambdaSet;
// Step 1: compile the app and generate the .o file // Step 1: compile the app and generate the .o file
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
function_kind, function_kind,
// TODO: expose this from CLI? // TODO: expose this from CLI?
render: roc_reporting::report::RenderTarget::ColorTerminal, render: roc_reporting::report::RenderTarget::ColorTerminal,
@ -536,7 +532,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
let (dyn_lib, expects_by_module, layout_interner) = let (dyn_lib, expects_by_module, layout_interner) =
roc_repl_expect::run::expect_mono_module_to_dylib( roc_repl_expect::run::expect_mono_module_to_dylib(
arena, arena,
target.clone(), target,
loaded, loaded,
opt_level, opt_level,
LlvmBackendMode::CliTest, LlvmBackendMode::CliTest,
@ -673,7 +669,7 @@ pub fn build(
matches: &ArgMatches, matches: &ArgMatches,
subcommands: &[String], subcommands: &[String],
config: BuildConfig, config: BuildConfig,
triple: Triple, target: Target,
out_path: Option<&Path>, out_path: Option<&Path>,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
link_type: LinkType, link_type: LinkType,
@ -784,7 +780,7 @@ pub fn build(
// Note: This allows using `--dev` with `--optimize`. // Note: This allows using `--dev` with `--optimize`.
// This means frontend optimizations and dev backend. // This means frontend optimizations and dev backend.
let code_gen_backend = if matches.get_flag(FLAG_DEV) { let code_gen_backend = if matches.get_flag(FLAG_DEV) {
if matches!(triple.architecture, Architecture::Wasm32) { if matches!(target.architecture(), Architecture::Wasm32) {
CodeGenBackend::Wasm CodeGenBackend::Wasm
} else { } else {
CodeGenBackend::Assembly(AssemblyBackendMode::Binary) CodeGenBackend::Assembly(AssemblyBackendMode::Binary)
@ -818,7 +814,7 @@ pub fn build(
let linking_strategy = if wasm_dev_backend { let linking_strategy = if wasm_dev_backend {
LinkingStrategy::Additive LinkingStrategy::Additive
} else if !roc_linker::supported(link_type, &triple) } else if !roc_linker::supported(link_type, target)
|| matches.get_one::<String>(FLAG_LINKER).map(|s| s.as_str()) == Some("legacy") || matches.get_one::<String>(FLAG_LINKER).map(|s| s.as_str()) == Some("legacy")
{ {
LinkingStrategy::Legacy LinkingStrategy::Legacy
@ -827,8 +823,8 @@ pub fn build(
}; };
let prebuilt = { let prebuilt = {
let cross_compile = triple != Triple::host(); let cross_compile = target != Target::default();
let targeting_wasm = matches!(triple.architecture, Architecture::Wasm32); let targeting_wasm = matches!(target.architecture(), Architecture::Wasm32);
matches.get_flag(FLAG_PREBUILT) || matches.get_flag(FLAG_PREBUILT) ||
// When compiling for a different target, assume a prebuilt platform. // When compiling for a different target, assume a prebuilt platform.
@ -862,11 +858,11 @@ pub fn build(
fuzz, 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( let res_binary_path = build_file(
&arena, &arena,
&triple, target,
path.to_owned(), path.to_owned(),
code_gen_options, code_gen_options,
emit_timings, emit_timings,
@ -933,7 +929,7 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually // ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap()); 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 => { BuildAndRunIfNoErrors => {
if problems.fatally_errored { if problems.fatally_errored {
@ -968,7 +964,7 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually // ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap()); 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<Item = &'a OsStr>>( fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
arena: &Bump, arena: &Bump,
opt_level: OptLevel, opt_level: OptLevel,
triple: Triple, target: Target,
args: I, args: I,
binary_bytes: &[u8], binary_bytes: &[u8],
expect_metadata: ExpectMetadata, expect_metadata: ExpectMetadata,
) -> io::Result<i32> { ) -> io::Result<i32> {
match triple.architecture { match target.architecture() {
Architecture::Wasm32 => { Architecture::Wasm32 => {
let executable = roc_run_executable_file_path(binary_bytes)?; let executable = roc_run_executable_file_path(binary_bytes)?;
let path = executable.as_path(); let path = executable.as_path();

View file

@ -15,7 +15,7 @@ use roc_gen_dev::AssemblyBackendMode;
use roc_gen_llvm::llvm::build::LlvmBackendMode; use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_load::{FunctionKind, LoadingProblem, Threading}; use roc_load::{FunctionKind, LoadingProblem, Threading};
use roc_packaging::cache::{self, RocCacheDir}; 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::fs::{self, FileType};
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -49,7 +49,7 @@ fn main() -> io::Result<()> {
&matches, &matches,
&subcommands, &subcommands,
BuildConfig::BuildAndRunIfNoErrors, BuildConfig::BuildAndRunIfNoErrors,
Triple::host(), Triple::host().into(),
None, None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable, LinkType::Executable,
@ -64,7 +64,7 @@ fn main() -> io::Result<()> {
matches, matches,
&subcommands, &subcommands,
BuildConfig::BuildAndRun, BuildConfig::BuildAndRun,
Triple::host(), Triple::host().into(),
None, None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable, LinkType::Executable,
@ -77,7 +77,7 @@ fn main() -> io::Result<()> {
} }
Some((CMD_TEST, matches)) => { Some((CMD_TEST, matches)) => {
if matches.contains_id(ROC_FILE) { if matches.contains_id(ROC_FILE) {
test(matches, Triple::host()) test(matches, Triple::host().into())
} else { } else {
eprintln!("What .roc file do you want to test? Specify it at the end of the `roc test` command."); 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, matches,
&subcommands, &subcommands,
BuildConfig::BuildAndRunIfNoErrors, BuildConfig::BuildAndRunIfNoErrors,
Triple::host(), Triple::host().into(),
None, None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable, LinkType::Executable,
@ -130,7 +130,7 @@ fn main() -> io::Result<()> {
roc_linker::generate_stub_lib( roc_linker::generate_stub_lib(
input_path, input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
&target.to_triple(), target,
function_kind, function_kind,
); );
Ok(0) Ok(0)
@ -142,24 +142,22 @@ fn main() -> io::Result<()> {
.and_then(|s| Target::from_str(s).ok()) .and_then(|s| Target::from_str(s).ok())
.unwrap_or_default(); .unwrap_or_default();
let triple = target.to_triple();
let function_kind = FunctionKind::LambdaSet; let function_kind = FunctionKind::LambdaSet;
let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib( let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib(
input_path, input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
&triple, target,
function_kind, function_kind,
); );
// TODO: pipeline the executable location through here. // TODO: pipeline the executable location through here.
// Currently it is essentally hardcoded as platform_path/dynhost. // Currently it is essentally hardcoded as platform_path/dynhost.
roc_linker::preprocess_host( roc_linker::preprocess_host(
&triple, target,
&platform_path.with_file_name("main.roc"), &platform_path.with_file_name("main.roc"),
// The target triple string must be derived from the triple to convert from the generic // The target triple string must be derived from the triple to convert from the generic
// `system` target to the exact specific target. // `system` target to the exact specific target.
&platform_path &platform_path.with_file_name(format!("{}.rh", target)),
.with_file_name(format!("{}.rh", get_target_triple_str(&triple).unwrap())),
&stub_lib, &stub_lib,
&stub_dll_symbols, &stub_dll_symbols,
); );
@ -184,7 +182,7 @@ fn main() -> io::Result<()> {
matches, matches,
&subcommands, &subcommands,
BuildConfig::BuildOnly, BuildConfig::BuildOnly,
target.to_triple(), target,
out_path, out_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
link_type, link_type,

View file

@ -1,9 +1,10 @@
use crate::target::{arch_str, target_zig_str}; use crate::target::arch_str;
use libloading::{Error, Library}; use libloading::{Error, Library};
use roc_command_utils::{cargo, clang, rustup, zig}; use roc_command_utils::{cargo, clang, rustup, zig};
use roc_debug_flags; use roc_debug_flags;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
use roc_target::{Architecture, OperatingSystem, Target};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsString; use std::ffi::OsString;
use std::fs::DirEntry; use std::fs::DirEntry;
@ -11,7 +12,6 @@ use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{self, Child, Command}; use std::process::{self, Child, Command};
use std::{env, fs}; use std::{env, fs};
use target_lexicon::{Architecture, OperatingSystem, Triple};
use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH}; use wasi_libc_sys::{WASI_COMPILER_RT_PATH, WASI_LIBC_PATH};
pub use roc_linker::LinkType; 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"] /// input_paths can include the host as well as the app. e.g. &["host.o", "roc_app.o"]
pub fn link( pub fn link(
target: &Triple, target: Target,
output_path: PathBuf, output_path: PathBuf,
input_paths: &[&str], input_paths: &[&str],
link_type: LinkType, link_type: LinkType,
) -> io::Result<(Child, PathBuf)> { ) -> io::Result<(Child, PathBuf)> {
match target { match target.arch_os() {
Triple { (Architecture::Wasm32, _) => link_wasm32(target, output_path, input_paths, link_type),
architecture: Architecture::Wasm32, (_, OperatingSystem::Linux) => link_linux(target, output_path, input_paths, link_type),
.. (_, OperatingSystem::Mac) => link_macos(target, output_path, input_paths, link_type),
} => link_wasm32(target, output_path, input_paths, link_type), (_, OperatingSystem::Windows) => link_windows(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),
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target),
} }
} }
/// Same format as the precompiled host filename, except with a file extension like ".o" or ".obj" /// 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<PathBuf> { pub fn legacy_host_file(target: Target, platform_main_roc: &Path) -> PathBuf {
let os = roc_target::OperatingSystem::from(target.operating_system); let lib_ext = target.static_library_file_ext();
let lib_ext = os.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); .replace(roc_linker::PRECOMPILED_HOST_EXT, lib_ext);
let lib_path = platform_main_roc.with_file_name(file_name); let lib_path = platform_main_roc.with_file_name(file_name);
if lib_path.exists() { if lib_path.exists() {
Some(lib_path) lib_path
} else { } else {
let obj_ext = os.object_file_ext(); let obj_ext = target.object_file_ext();
Some(lib_path.with_extension(obj_ext)) lib_path.with_extension(obj_ext)
} }
} }
@ -316,7 +303,7 @@ pub fn build_zig_host_wasm32(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn build_c_host_native( pub fn build_c_host_native(
target: &Triple, target: Target,
env_path: &str, env_path: &str,
env_home: &str, env_home: &str,
env_cpath: &str, env_cpath: &str,
@ -335,7 +322,7 @@ pub fn build_c_host_native(
.args(sources) .args(sources)
.args(["-o", dest]); .args(["-o", dest]);
if let Some(shared_lib_path) = shared_lib_path { if let Some(shared_lib_path) = shared_lib_path {
match target.operating_system { match target.operating_system() {
OperatingSystem::Windows => { OperatingSystem::Windows => {
// just use zig as a C compiler // just use zig as a C compiler
@ -347,7 +334,7 @@ pub fn build_c_host_native(
env_home, env_home,
dest, dest,
sources[0], sources[0],
get_target_str(target), "native",
opt_level, opt_level,
Some(shared_lib_path), Some(shared_lib_path),
builtins_host_path, builtins_host_path,
@ -406,7 +393,7 @@ pub fn build_swift_host_native(
.env("HOME", env_home); .env("HOME", env_home);
match arch { match arch {
Architecture::Aarch64(_) => command.arg("-arm64"), Architecture::Aarch64 => command.arg("-arm64"),
_ => command.arg(format!("-{arch}")), _ => command.arg(format!("-{arch}")),
}; };
@ -437,7 +424,7 @@ pub fn build_swift_host_native(
pub fn rebuild_host( pub fn rebuild_host(
opt_level: OptLevel, opt_level: OptLevel,
target: &Triple, target: Target,
platform_main_roc: &Path, platform_main_roc: &Path,
shared_lib_path: Option<&Path>, shared_lib_path: Option<&Path>,
) -> PathBuf { ) -> PathBuf {
@ -450,14 +437,12 @@ pub fn rebuild_host(
let swift_host_src = platform_main_roc.with_file_name("host.swift"); 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 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 target.operating_system() {
let executable_extension = match os { OperatingSystem::Windows => "exe",
roc_target::OperatingSystem::Windows => "exe", _ => "",
roc_target::OperatingSystem::Unix => "",
roc_target::OperatingSystem::Wasi => "",
}; };
let host_dest = if matches!(target.architecture, Architecture::Wasm32) { let host_dest = if matches!(target.architecture(), Architecture::Wasm32) {
if matches!(opt_level, OptLevel::Development) { if matches!(opt_level, OptLevel::Development) {
platform_main_roc.with_extension("o") platform_main_roc.with_extension("o")
} else { } else {
@ -468,7 +453,7 @@ pub fn rebuild_host(
.with_file_name("dynhost") .with_file_name("dynhost")
.with_extension(executable_extension) .with_extension(executable_extension)
} else { } 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()); let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string());
@ -480,7 +465,7 @@ pub fn rebuild_host(
if zig_host_src.exists() { if zig_host_src.exists() {
// Compile host.zig // Compile host.zig
let zig_cmd = match target.architecture { let zig_cmd = match target.architecture() {
Architecture::Wasm32 => { Architecture::Wasm32 => {
let emit_bin = if matches!(opt_level, OptLevel::Development) { let emit_bin = if matches!(opt_level, OptLevel::Development) {
format!("-femit-bin={}", host_dest.to_str().unwrap()) format!("-femit-bin={}", host_dest.to_str().unwrap())
@ -501,12 +486,12 @@ pub fn rebuild_host(
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
get_target_str(target), "native",
opt_level, opt_level,
shared_lib_path, shared_lib_path,
builtins_host_tempfile.path(), builtins_host_tempfile.path(),
), ),
Architecture::X86_32(_) => build_zig_host_native( Architecture::X86_32 => build_zig_host_native(
&env_path, &env_path,
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
@ -516,17 +501,17 @@ pub fn rebuild_host(
shared_lib_path, shared_lib_path,
builtins_host_tempfile.path(), builtins_host_tempfile.path(),
), ),
Architecture::Aarch64(_) => build_zig_host_native( Architecture::Aarch64 => build_zig_host_native(
&env_path, &env_path,
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
target_zig_str(target), "native",
opt_level, opt_level,
shared_lib_path, shared_lib_path,
builtins_host_tempfile.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); run_build_command(zig_cmd, "host.zig", 0);
@ -714,7 +699,7 @@ pub fn rebuild_host(
swift_host_header_src swift_host_header_src
.exists() .exists()
.then(|| swift_host_header_src.to_str().unwrap()), .then(|| swift_host_header_src.to_str().unwrap()),
target.architecture, target.architecture(),
); );
run_build_command(swiftc_cmd, "host.swift", 0); 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<Dir
matching_dirs matching_dirs
} }
fn get_target_str(target: &Triple) -> &str {
if target.operating_system == OperatingSystem::Windows
&& target.environment == target_lexicon::Environment::Gnu
{
"x86_64-windows-gnu"
} else {
"native"
}
}
fn nix_paths() -> Vec<String> { fn nix_paths() -> Vec<String> {
let mut paths = vec![]; let mut paths = vec![];
@ -862,12 +837,12 @@ fn extra_link_flags() -> Vec<String> {
} }
fn link_linux( fn link_linux(
target: &Triple, target: Target,
output_path: PathBuf, output_path: PathBuf,
input_paths: &[&str], input_paths: &[&str],
link_type: LinkType, link_type: LinkType,
) -> io::Result<(Child, PathBuf)> { ) -> io::Result<(Child, PathBuf)> {
let architecture = format!("{}-linux-gnu", target.architecture); let architecture = format!("{}-linux-gnu", target.architecture());
// Command::new("cp") // Command::new("cp")
// .args(&[input_paths[0], "/home/folkertdev/roc/wasm/host.o"]) // .args(&[input_paths[0], "/home/folkertdev/roc/wasm/host.o"])
@ -879,7 +854,7 @@ fn link_linux(
// .output() // .output()
// .unwrap(); // .unwrap();
if let Architecture::X86_32(_) = target.architecture { if let Architecture::X86_32 = target.architecture() {
return Ok(( return Ok((
zig() zig()
.args(["build-exe"]) .args(["build-exe"])
@ -971,7 +946,7 @@ fn link_linux(
scrt1_path.to_string_lossy(), scrt1_path.to_string_lossy(),
); );
let ld_linux_path = match target.architecture { let ld_linux_path = match target.architecture() {
Architecture::X86_64 => { Architecture::X86_64 => {
// give preference to nix_path if it's defined, this prevents bugs // give preference to nix_path if it's defined, this prevents bugs
if let Some(nix_glibc_path) = nix_glibc_path_opt() { 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"]) 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!( _ => internal_error!(
"TODO gracefully handle unsupported linux architecture: {:?}", "TODO gracefully handle unsupported linux architecture: {:?}",
target.architecture target.architecture()
), ),
}; };
@ -1083,7 +1058,7 @@ fn link_linux(
} }
fn link_macos( fn link_macos(
target: &Triple, target: Target,
output_path: PathBuf, output_path: PathBuf,
input_paths: &[&str], input_paths: &[&str],
link_type: LinkType, 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"), LinkType::None => internal_error!("link_macos should not be called with link type of none"),
}; };
let arch = match target.architecture { let arch = match target.architecture() {
Architecture::Aarch64(_) => "arm64".to_string(), Architecture::Aarch64 => "arm64".to_string(),
_ => target.architecture.to_string(), _ => target.architecture().to_string(),
}; };
let mut ld_command = Command::new("ld"); let mut ld_command = Command::new("ld");
@ -1177,8 +1152,8 @@ fn link_macos(
let mut ld_child = ld_command.spawn()?; let mut ld_child = ld_command.spawn()?;
match target.architecture { match target.architecture() {
Architecture::Aarch64(_) => { Architecture::Aarch64 => {
ld_child.wait()?; ld_child.wait()?;
let mut codesign_cmd = Command::new("codesign"); let mut codesign_cmd = Command::new("codesign");
@ -1214,7 +1189,7 @@ fn get_macos_version() -> String {
} }
fn link_wasm32( fn link_wasm32(
_target: &Triple, _target: Target,
output_path: PathBuf, output_path: PathBuf,
input_paths: &[&str], input_paths: &[&str],
_link_type: LinkType, _link_type: LinkType,
@ -1249,7 +1224,6 @@ fn link_wasm32(
} }
fn link_windows( fn link_windows(
target: &Triple,
output_path: PathBuf, output_path: PathBuf,
input_paths: &[&str], input_paths: &[&str],
link_type: LinkType, link_type: LinkType,
@ -1282,7 +1256,7 @@ fn link_windows(
.args(input_paths) .args(input_paths)
.args([ .args([
"-target", "-target",
get_target_str(target), "native",
"--subsystem", "--subsystem",
"console", "console",
"-lc", "-lc",
@ -1298,7 +1272,7 @@ fn link_windows(
pub fn llvm_module_to_dylib( pub fn llvm_module_to_dylib(
module: &inkwell::module::Module, module: &inkwell::module::Module,
target: &Triple, target: Target,
opt_level: OptLevel, opt_level: OptLevel,
) -> Result<Library, Error> { ) -> Result<Library, Error> {
use crate::target::{self, convert_opt_level}; 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 // Link app.o into a dylib - e.g. app.so or app.dylib
let (mut child, dylib_path) = link( let (mut child, dylib_path) = link(
&Triple::host(), target,
app_o_file.clone(), app_o_file.clone(),
&[app_o_file.to_str().unwrap()], &[app_o_file.to_str().unwrap()],
LinkType::Dylib, LinkType::Dylib,
@ -1339,7 +1313,7 @@ pub fn llvm_module_to_dylib(
// Load the dylib // Load the dylib
let path = dylib_path.as_path().to_str().unwrap(); 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 // On AArch64 darwin machines, calling `ldopen` on Roc-generated libs from multiple threads
// sometimes fails with // sometimes fails with
// cannot dlopen until fork() handlers have completed // cannot dlopen until fork() handlers have completed

View file

@ -17,7 +17,7 @@ use roc_reporting::{
cli::{report_problems, Problems}, cli::{report_problems, Problems},
report::{RenderTarget, DEFAULT_PALETTE}, report::{RenderTarget, DEFAULT_PALETTE},
}; };
use roc_target::{OperatingSystem, TargetInfo}; use roc_target::{Architecture, Target};
use std::ffi::OsStr; use std::ffi::OsStr;
use std::ops::Deref; use std::ops::Deref;
use std::{ use std::{
@ -25,7 +25,6 @@ use std::{
thread::JoinHandle, thread::JoinHandle,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use target_lexicon::Triple;
#[cfg(feature = "target-wasm32")] #[cfg(feature = "target-wasm32")]
use roc_collections::all::MutSet; use roc_collections::all::MutSet;
@ -96,7 +95,7 @@ pub fn gen_from_mono_module<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
roc_file_path: &Path, roc_file_path: &Path,
target: &target_lexicon::Triple, target: Target,
code_gen_options: CodeGenOptions, code_gen_options: CodeGenOptions,
preprocessed_host_path: &Path, preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>, wasm_dev_stack_bytes: Option<u32>,
@ -146,7 +145,7 @@ fn gen_from_mono_module_llvm<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
roc_file_path: &Path, roc_file_path: &Path,
target: &target_lexicon::Triple, target: Target,
opt_level: OptLevel, opt_level: OptLevel,
backend_mode: LlvmBackendMode, backend_mode: LlvmBackendMode,
emit_debug_info: bool, emit_debug_info: bool,
@ -162,7 +161,6 @@ fn gen_from_mono_module_llvm<'a>(
let all_code_gen_start = Instant::now(); let all_code_gen_start = Instant::now();
// Generate the binary // Generate the binary
let target_info = roc_target::TargetInfo::from(target);
let context = Context::create(); let context = Context::create();
let module = arena.alloc(module_from_builtins(target, &context, "app")); let module = arena.alloc(module_from_builtins(target, &context, "app"));
@ -210,7 +208,7 @@ fn gen_from_mono_module_llvm<'a>(
context: &context, context: &context,
interns: loaded.interns, interns: loaded.interns,
module, module,
target_info, target,
mode: backend_mode, mode: backend_mode,
exposed_to_host: loaded exposed_to_host: loaded
@ -387,9 +385,8 @@ fn gen_from_mono_module_llvm<'a>(
} }
// Emit the .o file // Emit the .o file
use target_lexicon::Architecture; match target.architecture() {
match target.architecture { Architecture::X86_64 | Architecture::X86_32 | Architecture::Aarch64 => {
Architecture::X86_64 | Architecture::X86_32(_) | Architecture::Aarch64(_) => {
let reloc = RelocMode::PIC; let reloc = RelocMode::PIC;
let target_machine = let target_machine =
target::target_machine(target, convert_opt_level(opt_level), reloc).unwrap(); target::target_machine(target, convert_opt_level(opt_level), reloc).unwrap();
@ -405,7 +402,7 @@ fn gen_from_mono_module_llvm<'a>(
} }
_ => internal_error!( _ => internal_error!(
"TODO gracefully handle unsupported architecture: {:?}", "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>( fn gen_from_mono_module_dev<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
target: &target_lexicon::Triple, target: Target,
preprocessed_host_path: &Path, preprocessed_host_path: &Path,
wasm_dev_stack_bytes: Option<u32>, wasm_dev_stack_bytes: Option<u32>,
backend_mode: AssemblyBackendMode, backend_mode: AssemblyBackendMode,
) -> GenFromMono<'a> { ) -> GenFromMono<'a> {
use target_lexicon::Architecture; match target.architecture() {
match target.architecture {
Architecture::Wasm32 => gen_from_mono_module_dev_wasm32( Architecture::Wasm32 => gen_from_mono_module_dev_wasm32(
arena, arena,
loaded, loaded,
preprocessed_host_path, preprocessed_host_path,
wasm_dev_stack_bytes, 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) gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode)
} }
_ => todo!(), _ => todo!(),
@ -457,15 +452,13 @@ fn gen_from_mono_module_dev<'a>(
pub fn gen_from_mono_module_dev<'a>( pub fn gen_from_mono_module_dev<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
target: &target_lexicon::Triple, target: Target,
_host_input_path: &Path, _host_input_path: &Path,
_wasm_dev_stack_bytes: Option<u32>, _wasm_dev_stack_bytes: Option<u32>,
backend_mode: AssemblyBackendMode, backend_mode: AssemblyBackendMode,
) -> GenFromMono<'a> { ) -> 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) gen_from_mono_module_dev_assembly(arena, loaded, target, backend_mode)
} }
_ => todo!(), _ => todo!(),
@ -549,7 +542,7 @@ fn gen_from_mono_module_dev_wasm32<'a>(
fn gen_from_mono_module_dev_assembly<'a>( fn gen_from_mono_module_dev_assembly<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
target: &target_lexicon::Triple, target: Target,
backend_mode: AssemblyBackendMode, backend_mode: AssemblyBackendMode,
) -> GenFromMono<'a> { ) -> GenFromMono<'a> {
let all_code_gen_start = Instant::now(); let all_code_gen_start = Instant::now();
@ -694,12 +687,10 @@ pub fn handle_loading_problem(problem: LoadingProblem) -> std::io::Result<i32> {
} }
pub fn standard_load_config( pub fn standard_load_config(
target: &Triple, target: Target,
order: BuildOrdering, order: BuildOrdering,
threading: Threading, threading: Threading,
) -> LoadConfig { ) -> LoadConfig {
let target_info = TargetInfo::from(target);
let exec_mode = match order { let exec_mode = match order {
BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck, BuildOrdering::BuildIfChecks => ExecutionMode::ExecutableIfCheck,
BuildOrdering::AlwaysBuild => ExecutionMode::Executable, BuildOrdering::AlwaysBuild => ExecutionMode::Executable,
@ -717,7 +708,7 @@ pub fn standard_load_config(
}; };
LoadConfig { LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::ColorTerminal, render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
@ -729,7 +720,7 @@ pub fn standard_load_config(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn build_file<'a>( pub fn build_file<'a>(
arena: &'a Bump, arena: &'a Bump,
target: &Triple, target: Target,
app_module_path: PathBuf, app_module_path: PathBuf,
code_gen_options: CodeGenOptions, code_gen_options: CodeGenOptions,
emit_timings: bool, emit_timings: bool,
@ -767,7 +758,7 @@ pub fn build_file<'a>(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn build_loaded_file<'a>( fn build_loaded_file<'a>(
arena: &'a Bump, arena: &'a Bump,
target: &Triple, target: Target,
app_module_path: PathBuf, app_module_path: PathBuf,
code_gen_options: CodeGenOptions, code_gen_options: CodeGenOptions,
emit_timings: bool, emit_timings: bool,
@ -779,8 +770,6 @@ fn build_loaded_file<'a>(
compilation_start: Instant, compilation_start: Instant,
out_path: Option<&Path>, out_path: Option<&Path>,
) -> Result<BuiltFile<'a>, BuildFileError<'a>> { ) -> Result<BuiltFile<'a>, BuildFileError<'a>> {
let operating_system = roc_target::OperatingSystem::from(target.operating_system);
let platform_main_roc = match &loaded.entry_point { let platform_main_roc = match &loaded.entry_point {
EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(), EntryPoint::Executable { platform_path, .. } => platform_path.to_path_buf(),
_ => unreachable!(), _ => unreachable!(),
@ -792,9 +781,9 @@ fn build_loaded_file<'a>(
if is_platform_prebuilt && linking_strategy == LinkingStrategy::Surgical { 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. // 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 let preprocessed_host_path =
.with_file_name(roc_linker::preprocessed_host_filename(target).unwrap()); platform_main_roc.with_file_name(roc_linker::preprocessed_host_filename(target));
let legacy_host_path = legacy_host_file(target, &platform_main_roc).unwrap(); let legacy_host_path = legacy_host_file(target, &platform_main_roc);
if !preprocessed_host_path.exists() && legacy_host_path.exists() { if !preprocessed_host_path.exists() && legacy_host_path.exists() {
linking_strategy = LinkingStrategy::Legacy; linking_strategy = LinkingStrategy::Legacy;
} }
@ -802,15 +791,15 @@ fn build_loaded_file<'a>(
// the preprocessed host is stored beside the platform's main.roc // the preprocessed host is stored beside the platform's main.roc
let preprocessed_host_path = if linking_strategy == LinkingStrategy::Legacy { 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 // when compiling a wasm application, we implicitly assume here that the host is in zig
// and has a file called "host.zig" // and has a file called "host.zig"
platform_main_roc.with_file_name("host.zig") platform_main_roc.with_file_name("host.zig")
} else { } else {
legacy_host_file(target, &platform_main_roc).unwrap() legacy_host_file(target, &platform_main_roc)
} }
} else { } 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 { let output_exe_path = match out_path {
@ -841,22 +830,12 @@ fn build_loaded_file<'a>(
if ends_with_sep { if ends_with_sep {
let filename = app_module_path.file_name().unwrap_or_default(); let filename = app_module_path.file_name().unwrap_or_default();
with_output_extension( with_output_extension(&path.join(filename), target, linking_strategy, link_type)
&path.join(filename),
operating_system,
linking_strategy,
link_type,
)
} else { } else {
path.to_path_buf() path.to_path_buf()
} }
} }
None => with_output_extension( None => with_output_extension(&app_module_path, target, linking_strategy, link_type),
&app_module_path,
operating_system,
linking_strategy,
link_type,
),
}; };
// We don't need to spawn a rebuild thread when using a prebuilt host. // 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(); std::fs::write(&output_exe_path, &*roc_app_bytes).unwrap();
} }
(LinkingStrategy::Legacy, _) => { (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. // 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. // 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. // If we set the extension wrong, zig will print a ton of warnings when linking.
"bc" "bc"
} else { } else {
operating_system.object_file_ext() target.object_file_ext()
}; };
let app_o_file = tempfile::Builder::new() let app_o_file = tempfile::Builder::new()
.prefix("roc_app") .prefix("roc_app")
@ -1124,10 +1103,9 @@ fn spawn_rebuild_thread(
platform_main_roc: PathBuf, platform_main_roc: PathBuf,
preprocessed_host_path: PathBuf, preprocessed_host_path: PathBuf,
output_exe_path: PathBuf, output_exe_path: PathBuf,
target: &Triple, target: Target,
dll_stub_symbols: Vec<String>, dll_stub_symbols: Vec<String>,
) -> std::thread::JoinHandle<u128> { ) -> std::thread::JoinHandle<u128> {
let thread_local_target = target.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
// Printing to stderr because we want stdout to contain only the output of the roc program. // Printing to stderr because we want stdout to contain only the output of the roc program.
// We are aware of the trade-offs. // We are aware of the trade-offs.
@ -1138,19 +1116,14 @@ fn spawn_rebuild_thread(
match linking_strategy { match linking_strategy {
LinkingStrategy::Additive => { LinkingStrategy::Additive => {
let host_dest = rebuild_host( let host_dest = rebuild_host(opt_level, target, platform_main_roc.as_path(), None);
opt_level,
&thread_local_target,
platform_main_roc.as_path(),
None,
);
preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path); preprocess_host_wasm32(host_dest.as_path(), &preprocessed_host_path);
} }
LinkingStrategy::Surgical => { LinkingStrategy::Surgical => {
build_and_preprocess_host_lowlevel( build_and_preprocess_host_lowlevel(
opt_level, opt_level,
&thread_local_target, target,
platform_main_roc.as_path(), platform_main_roc.as_path(),
preprocessed_host_path.as_path(), preprocessed_host_path.as_path(),
&dll_stub_symbols, &dll_stub_symbols,
@ -1161,12 +1134,7 @@ fn spawn_rebuild_thread(
std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap(); std::fs::copy(&preprocessed_host_path, output_exe_path.as_path()).unwrap();
} }
LinkingStrategy::Legacy => { LinkingStrategy::Legacy => {
rebuild_host( rebuild_host(opt_level, target, platform_main_roc.as_path(), None);
opt_level,
&thread_local_target,
platform_main_roc.as_path(),
None,
);
} }
} }
@ -1176,7 +1144,7 @@ fn spawn_rebuild_thread(
pub fn build_and_preprocess_host( pub fn build_and_preprocess_host(
opt_level: OptLevel, opt_level: OptLevel,
target: &Triple, target: Target,
platform_main_roc: &Path, platform_main_roc: &Path,
preprocessed_host_path: &Path, preprocessed_host_path: &Path,
exposed_symbols: roc_linker::ExposedSymbols, exposed_symbols: roc_linker::ExposedSymbols,
@ -1194,7 +1162,7 @@ pub fn build_and_preprocess_host(
fn build_and_preprocess_host_lowlevel( fn build_and_preprocess_host_lowlevel(
opt_level: OptLevel, opt_level: OptLevel,
target: &Triple, target: Target,
platform_main_roc: &Path, platform_main_roc: &Path,
preprocessed_host_path: &Path, preprocessed_host_path: &Path,
stub_dll_symbols: &[String], 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 // only used for generating errors. We don't do code generation, so hardcoding should be fine
// we need monomorphization for when exhaustiveness checking // 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 // Step 1: compile the app and generate the .o file
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
// TODO: we may not want this for just checking. // TODO: we may not want this for just checking.
function_kind: FunctionKind::LambdaSet, function_kind: FunctionKind::LambdaSet,
// TODO: expose this from CLI? // TODO: expose this from CLI?
@ -1295,7 +1263,7 @@ pub fn build_str_test<'a>(
app_module_source: &'a str, app_module_source: &'a str,
assume_prebuild: bool, assume_prebuild: bool,
) -> Result<BuiltFile<'a>, BuildFileError<'a>> { ) -> Result<BuiltFile<'a>, BuildFileError<'a>> {
let triple = target_lexicon::Triple::host(); let target = target_lexicon::Triple::host().into();
let code_gen_options = CodeGenOptions { let code_gen_options = CodeGenOptions {
backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary), backend: CodeGenBackend::Llvm(LlvmBackendMode::Binary),
@ -1314,7 +1282,7 @@ pub fn build_str_test<'a>(
let build_ordering = BuildOrdering::AlwaysBuild; let build_ordering = BuildOrdering::AlwaysBuild;
let threading = Threading::AtMost(2); 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(); let compilation_start = std::time::Instant::now();
@ -1331,7 +1299,7 @@ pub fn build_str_test<'a>(
build_loaded_file( build_loaded_file(
arena, arena,
&triple, target,
app_module_path.to_path_buf(), app_module_path.to_path_buf(),
code_gen_options, code_gen_options,
emit_timings, emit_timings,
@ -1347,15 +1315,15 @@ pub fn build_str_test<'a>(
fn with_output_extension( fn with_output_extension(
path: &Path, path: &Path,
os: OperatingSystem, target: Target,
linking_strategy: LinkingStrategy, linking_strategy: LinkingStrategy,
link_type: LinkType, link_type: LinkType,
) -> PathBuf { ) -> PathBuf {
match (linking_strategy, link_type) { match (linking_strategy, link_type) {
(LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => { (LinkingStrategy::Additive, _) | (LinkingStrategy::Legacy, LinkType::None) => {
// Additive linking and no linking both output the object file type. // 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()),
} }
} }

View file

@ -1,121 +1,65 @@
use inkwell::{ use inkwell::{
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple}, targets::{
CodeModel, InitializationConfig, RelocMode, Target as LlvmTarget, TargetMachine,
TargetTriple,
},
OptimizationLevel, OptimizationLevel,
}; };
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_mono::ir::OptLevel; 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: // Best guide I've found on how to determine these magic strings:
// //
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures // https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
match target { match target {
Triple { Target::LinuxArm64 => "aarch64-unknown-linux-gnu",
architecture: Architecture::X86_64, Target::LinuxX32 => "i386-unknown-linux-gnu",
operating_system: OperatingSystem::Linux, Target::LinuxX64 => "x86_64-unknown-linux-gnu",
.. Target::MacArm64 => "aarch64-apple-darwin",
} => "x86_64-unknown-linux-gnu", Target::MacX64 => "x86_64-unknown-darwin10",
Triple { Target::Wasm32 => "wasm32-unknown-unknown",
architecture: Architecture::X86_32(target_lexicon::X86_32Architecture::I386), Target::WinX64 => "x86_64-pc-windows-gnu",
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",
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), _ => 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: // Zig has its own architecture mappings, defined here:
// https://github.com/ziglang/zig/blob/master/tools/process_headers.zig // https://github.com/ziglang/zig/blob/master/tools/process_headers.zig
// //
// and an open proposal to unify them with the more typical "target triples": // and an open proposal to unify them with the more typical "target triples":
// https://github.com/ziglang/zig/issues/4911 // https://github.com/ziglang/zig/issues/4911
match target { match target {
Triple { Target::LinuxArm64 => "aarch64-linux-gnu",
architecture: Architecture::X86_64, Target::LinuxX32 => "i386-linux-gnu",
operating_system: OperatingSystem::Linux, Target::LinuxX64 => "x86_64-linux-gnu",
environment: Environment::Musl, Target::MacArm64 => "aarch64-macos-none",
.. Target::MacX64 => "x86_64-macos-none",
} => "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",
_ => internal_error!("TODO gracefully handle unsupported target: {:?}", target), _ => internal_error!("TODO gracefully handle unsupported target: {:?}", target),
} }
} }
pub fn init_arch(target: &Triple) { pub fn init_arch(target: Target) {
match target.architecture { match target.architecture() {
Architecture::X86_64 | Architecture::X86_32(_) Architecture::X86_64 | Architecture::X86_32
if cfg!(any(feature = "target-x86", feature = "target-x86_64")) => 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") => { Architecture::Aarch64 if cfg!(feature = "target-aarch64") => {
Target::initialize_aarch64(&InitializationConfig::default()); LlvmTarget::initialize_aarch64(&InitializationConfig::default());
} }
Architecture::Arm(_) if cfg!(feature = "target-arm") => { Architecture::Aarch32 if cfg!(feature = "target-arm") => {
Target::initialize_arm(&InitializationConfig::default()); LlvmTarget::initialize_arm(&InitializationConfig::default());
} }
Architecture::Wasm32 if cfg!(feature = "target-wasm32") => { Architecture::Wasm32 if cfg!(feature = "target-wasm32") => {
Target::initialize_webassembly(&InitializationConfig::default()); LlvmTarget::initialize_webassembly(&InitializationConfig::default());
} }
_ => internal_error!( _ => internal_error!(
"TODO gracefully handle unsupported target architecture: {:?}", "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 /// 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 /// string! For example, if it's "x86-64" here, the magic target triple string
/// will begin with "x86_64" (with an underscore) instead. /// 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: // Best guide I've found on how to determine these magic strings:
// //
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures // https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
match target.architecture { match target.architecture() {
Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64", roc_target::Architecture::X86_64 if cfg!(feature = "target-x86_64") => "x86-64",
Architecture::X86_32(_) if cfg!(feature = "target-x86") => "x86", roc_target::Architecture::X86_32 if cfg!(feature = "target-x86") => "x86",
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => "aarch64", roc_target::Architecture::Aarch64 if cfg!(feature = "target-aarch64") => "aarch64",
Architecture::Arm(_) if cfg!(feature = "target-arm") => "arm", roc_target::Architecture::Aarch32 if cfg!(feature = "target-arm") => "arm",
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32", roc_target::Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32",
_ => internal_error!( _ => internal_error!(
"TODO gracefully handle unsupported target architecture: {:?}", "TODO gracefully handle unsupported target architecture: {:?}",
target.architecture target.architecture()
), ),
} }
} }
pub fn target_machine( pub fn target_machine(
target: &Triple, target: Target,
opt: OptimizationLevel, opt: OptimizationLevel,
reloc: RelocMode, reloc: RelocMode,
) -> Option<TargetMachine> { ) -> Option<TargetMachine> {
@ -150,11 +94,7 @@ pub fn target_machine(
init_arch(target); init_arch(target);
let code_model = match target { let code_model = match target {
Triple { Target::MacArm64 => {
operating_system: OperatingSystem::Darwin,
architecture: Architecture::Aarch64(_),
..
} => {
// We used to have a problem that LLVM 12 would not compile our programs without a large code model. // 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 // The reason was not totally clear to us, but one guess is a few special-cases in
// llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (instructions) // llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (instructions)
@ -168,7 +108,7 @@ pub fn target_machine(
_ => CodeModel::Default, _ => CodeModel::Default,
}; };
Target::from_name(arch).unwrap().create_target_machine( LlvmTarget::from_name(arch).unwrap().create_target_machine(
&TargetTriple::create(target_triple_str(target)), &TargetTriple::create(target_triple_str(target)),
"generic", "generic",
"", "",

View file

@ -1,5 +1,5 @@
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_target::TargetInfo; use roc_target::Target;
use std::ops::Index; use std::ops::Index;
#[derive(Debug, Default, Copy, Clone)] #[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 roc_target::Architecture::*;
use FloatWidth::*; use FloatWidth::*;
@ -47,7 +47,7 @@ impl FloatWidth {
// the compiler is targeting (e.g. what the Roc code will be compiled to). // the compiler is targeting (e.g. what the Roc code will be compiled to).
match self { match self {
F32 => 4, F32 => 4,
F64 => match target_info.architecture { F64 => match target.architecture() {
X86_64 | Aarch64 | Wasm32 => 8, X86_64 | Aarch64 | Wasm32 => 8,
X86_32 | Aarch32 => 4, 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 roc_target::Architecture;
use IntWidth::*; use IntWidth::*;
@ -118,7 +118,7 @@ impl IntWidth {
U8 | I8 => 1, U8 | I8 => 1,
U16 | I16 => 2, U16 | I16 => 2,
U32 | I32 => 4, U32 | I32 => 4,
U64 | I64 => match target_info.architecture { U64 | I64 => match target.architecture() {
Architecture::X86_64 Architecture::X86_64
| Architecture::Aarch64 | Architecture::Aarch64
| Architecture::Aarch32 | Architecture::Aarch32
@ -131,7 +131,7 @@ impl IntWidth {
// //
// however, rust does not always think that this is true // 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. // 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::X86_64 | Architecture::Aarch64 | Architecture::X86_32 => 16,
Architecture::Aarch32 | Architecture::Wasm32 => 8, Architecture::Aarch32 | Architecture::Wasm32 => 8,
} }

View file

@ -17,7 +17,7 @@ use roc_mono::layout::{
TagIdIntType, UnionLayout, TagIdIntType, UnionLayout,
}; };
use roc_mono::low_level::HigherOrder; use roc_mono::low_level::HigherOrder;
use roc_target::TargetInfo; use roc_target::Target;
use std::marker::PhantomData; use std::marker::PhantomData;
pub(crate) mod aarch64; pub(crate) mod aarch64;
@ -790,7 +790,7 @@ pub fn new_backend_64bit<
CC: CallConv<GeneralReg, FloatReg, ASM>, CC: CallConv<GeneralReg, FloatReg, ASM>,
>( >(
env: &'r Env<'a>, env: &'r Env<'a>,
target_info: TargetInfo, target: Target,
interns: &'r mut Interns, interns: &'r mut Interns,
layout_interner: &'r mut STLayoutInterner<'a>, layout_interner: &'r mut STLayoutInterner<'a>,
) -> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC> { ) -> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC> {
@ -800,7 +800,7 @@ pub fn new_backend_64bit<
env, env,
interns, interns,
layout_interner, 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], helper_proc_symbols: bumpalo::vec![in env.arena],
caller_procs: bumpalo::vec![in env.arena], caller_procs: bumpalo::vec![in env.arena],
proc_name: None, proc_name: None,
@ -812,7 +812,7 @@ pub fn new_backend_64bit<
free_map: MutMap::default(), free_map: MutMap::default(),
literal_map: MutMap::default(), literal_map: MutMap::default(),
join_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> { fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation> {
&mut self.relocs &mut self.relocs
} }
fn target_info(&self) -> TargetInfo { fn target(&self) -> Target {
self.storage_manager.target_info self.storage_manager.target
} }
fn module_interns_helpers_mut( fn module_interns_helpers_mut(
&mut self, &mut self,
@ -3627,7 +3627,7 @@ impl<
// mask out the tag id bits // mask out the tag id bits
let (unmasked_symbol, unmasked_reg) = 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) (None, ptr_reg)
} else { } else {
let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg);
@ -3728,7 +3728,7 @@ impl<
// mask out the tag id bits // mask out the tag id bits
let (unmasked_symbol, unmasked_reg) = 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) (None, ptr_reg)
} else { } else {
let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg); let (mask_symbol, mask_reg) = self.clear_tag_id(ptr_reg);
@ -4007,8 +4007,8 @@ impl<
UnionLayout::Recursive(_) => { UnionLayout::Recursive(_) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, sym); let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
let target_info = self.storage_manager.target_info; let target = self.storage_manager.target;
if union_layout.stores_tag_id_as_data(target_info) { if union_layout.stores_tag_id_as_data(target) {
let offset = union_layout.tag_id_offset(self.interner()).unwrap() as i32; let offset = union_layout.tag_id_offset(self.interner()).unwrap() as i32;
let ptr_reg = self let ptr_reg = self
@ -4173,7 +4173,7 @@ impl<
.unwrap(); .unwrap();
let largest_variant = 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 self.layout_interner
.insert_direct_no_semantic(LayoutRepr::Struct( .insert_direct_no_semantic(LayoutRepr::Struct(
self.env.arena.alloc([largest_variant_fields, Layout::U8]), self.env.arena.alloc([largest_variant_fields, Layout::U8]),
@ -4214,7 +4214,7 @@ impl<
}; };
// finally, we need to tag the pointer // 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 // allocate space on the stack for the whole tag payload
let scratch_space = self.debug_symbol("scratch_space"); let scratch_space = self.debug_symbol("scratch_space");
let (data_size, data_alignment) = let (data_size, data_alignment) =
@ -4290,7 +4290,7 @@ impl<
let other_fields = tags[tag_id as usize]; let other_fields = tags[tag_id as usize];
let stores_tag_id_as_data = 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 let (largest_variant_fields, _largest_variant_size) = tags
.iter() .iter()

View file

@ -14,7 +14,7 @@ use roc_mono::{
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout, Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
}, },
}; };
use roc_target::TargetInfo; use roc_target::Target;
use std::cmp::max; use std::cmp::max;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
@ -92,7 +92,7 @@ pub struct StorageManager<
phantom_cc: PhantomData<CC>, phantom_cc: PhantomData<CC>,
phantom_asm: PhantomData<ASM>, phantom_asm: PhantomData<ASM>,
pub(crate) env: &'r Env<'a>, pub(crate) env: &'r Env<'a>,
pub(crate) target_info: TargetInfo, pub(crate) target: Target,
// Data about where each symbol is stored. // Data about where each symbol is stored.
symbol_storage_map: MutMap<Symbol, Storage<GeneralReg, FloatReg>>, symbol_storage_map: MutMap<Symbol, Storage<GeneralReg, FloatReg>>,
@ -137,13 +137,13 @@ pub fn new_storage_manager<
CC: CallConv<GeneralReg, FloatReg, ASM>, CC: CallConv<GeneralReg, FloatReg, ASM>,
>( >(
env: &'r Env<'a>, env: &'r Env<'a>,
target_info: TargetInfo, target: Target,
) -> StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC> { ) -> StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC> {
StorageManager { StorageManager {
phantom_asm: PhantomData, phantom_asm: PhantomData,
phantom_cc: PhantomData, phantom_cc: PhantomData,
env, env,
target_info, target,
symbol_storage_map: MutMap::default(), symbol_storage_map: MutMap::default(),
allocation_map: MutMap::default(), allocation_map: MutMap::default(),
join_param_map: MutMap::default(), join_param_map: MutMap::default(),

View file

@ -28,7 +28,7 @@ use roc_mono::list_element_layout;
mod generic64; mod generic64;
mod object_builder; mod object_builder;
pub use object_builder::build_module; pub use object_builder::build_module;
use roc_target::TargetInfo; use roc_target::Target;
mod run_roc; mod run_roc;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -312,7 +312,7 @@ trait Backend<'a> {
fn interns_mut(&mut self) -> &mut Interns; fn interns_mut(&mut self) -> &mut Interns;
fn interner(&self) -> &STLayoutInterner<'a>; fn interner(&self) -> &STLayoutInterner<'a>;
fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation>; 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> { fn interner_mut(&mut self) -> &mut STLayoutInterner<'a> {
self.module_interns_helpers_mut().1 self.module_interns_helpers_mut().1

View file

@ -14,8 +14,7 @@ use roc_module::symbol::Interns;
use roc_mono::ir::{Call, CallSpecId, Expr, UpdateModeId}; use roc_mono::ir::{Call, CallSpecId, Expr, UpdateModeId};
use roc_mono::ir::{Proc, ProcLayout, Stmt}; use roc_mono::ir::{Proc, ProcLayout, Stmt};
use roc_mono::layout::{LambdaName, Layout, LayoutIds, LayoutInterner, STLayoutInterner}; use roc_mono::layout::{LambdaName, Layout, LayoutIds, LayoutInterner, STLayoutInterner};
use roc_target::TargetInfo; use roc_target::Target;
use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Triple};
// This is used by some code below which is currently commented out. // This is used by some code below which is currently commented out.
// See that code for more details! // See that code for more details!
@ -27,7 +26,7 @@ pub fn build_module<'a, 'r>(
env: &'r Env<'a>, env: &'r Env<'a>,
interns: &'r mut Interns, interns: &'r mut Interns,
layout_interner: &'r mut STLayoutInterner<'a>, layout_interner: &'r mut STLayoutInterner<'a>,
target: &Triple, target: Target,
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>, procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
) -> Object<'a> { ) -> Object<'a> {
let module_object = build_module_help(env, interns, layout_interner, target, procedures); 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>, env: &'r Env<'a>,
interns: &'r mut Interns, interns: &'r mut Interns,
layout_interner: &'r mut STLayoutInterner<'a>, layout_interner: &'r mut STLayoutInterner<'a>,
target: &Triple, target: Target,
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>, procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
) -> Object<'a> { ) -> Object<'a> {
match target { match target {
Triple { Target::LinuxX64 if cfg!(feature = "target-x86_64") => {
architecture: TargetArch::X86_64,
binary_format: TargetBF::Elf,
..
} if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::< let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg, x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg, x86_64::X86_64FloatReg,
x86_64::X86_64Assembler, x86_64::X86_64Assembler,
x86_64::X86_64SystemV, 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. // Newer version of `ld` require `.note.GNU-stack` for security reasons.
// It specifies that we will not execute code stored on the stack. // It specifies that we will not execute code stored on the stack.
let mut object = let mut object =
@ -75,17 +70,13 @@ fn build_module_help<'a, 'r>(
); );
build_object(procedures, backend, object) build_object(procedures, backend, object)
} }
Triple { Target::MacX64 if cfg!(feature = "target-x86_64") => {
architecture: TargetArch::X86_64,
binary_format: TargetBF::Macho,
..
} if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::< let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg, x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg, x86_64::X86_64FloatReg,
x86_64::X86_64Assembler, x86_64::X86_64Assembler,
x86_64::X86_64SystemV, x86_64::X86_64SystemV,
>(env, TargetInfo::default_x86_64(), interns, layout_interner); >(env, target, interns, layout_interner);
build_object( build_object(
procedures, procedures,
backend, backend,
@ -96,53 +87,39 @@ fn build_module_help<'a, 'r>(
), ),
) )
} }
Triple { Target::WinX64 if cfg!(feature = "target-x86_64") => {
architecture: TargetArch::X86_64,
binary_format: TargetBF::Coff,
..
} if cfg!(feature = "target-x86_64") => {
let backend = new_backend_64bit::< let backend = new_backend_64bit::<
x86_64::X86_64GeneralReg, x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg, x86_64::X86_64FloatReg,
x86_64::X86_64Assembler, x86_64::X86_64Assembler,
x86_64::X86_64WindowsFastcall, x86_64::X86_64WindowsFastcall,
>(env, TargetInfo::default_x86_64(), interns, layout_interner); >(env, target, interns, layout_interner);
build_object( build_object(
procedures, procedures,
backend, backend,
Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little), Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little),
) )
} }
Triple { Target::LinuxArm64 if cfg!(feature = "target-aarch64") => {
architecture: TargetArch::Aarch64(_), let backend = new_backend_64bit::<
binary_format: TargetBF::Elf,
..
} if cfg!(feature = "target-aarch64") => {
let backend =
new_backend_64bit::<
aarch64::AArch64GeneralReg, aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg, aarch64::AArch64FloatReg,
aarch64::AArch64Assembler, aarch64::AArch64Assembler,
aarch64::AArch64Call, aarch64::AArch64Call,
>(env, TargetInfo::default_aarch64(), interns, layout_interner); >(env, target, interns, layout_interner);
build_object( build_object(
procedures, procedures,
backend, backend,
Object::new(BinaryFormat::Elf, Architecture::Aarch64, Endianness::Little), Object::new(BinaryFormat::Elf, Architecture::Aarch64, Endianness::Little),
) )
} }
Triple { Target::MacArm64 if cfg!(feature = "target-aarch64") => {
architecture: TargetArch::Aarch64(_), let backend = new_backend_64bit::<
binary_format: TargetBF::Macho,
..
} if cfg!(feature = "target-aarch64") => {
let backend =
new_backend_64bit::<
aarch64::AArch64GeneralReg, aarch64::AArch64GeneralReg,
aarch64::AArch64FloatReg, aarch64::AArch64FloatReg,
aarch64::AArch64Assembler, aarch64::AArch64Assembler,
aarch64::AArch64Call, aarch64::AArch64Call,
>(env, TargetInfo::default_aarch64(), interns, layout_interner); >(env, target, interns, layout_interner);
build_object( build_object(
procedures, procedures,
backend, backend,
@ -394,7 +371,7 @@ fn generate_wrapper<'a, B: Backend<'a>>(
}; };
output.add_symbol(symbol); output.add_symbol(symbol);
if let Some(sym_id) = output.symbol_id(name) { 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) { match output.add_relocation(text_section, reloc) {
Ok(obj) => obj, 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 { fn create_relocation(target: Target, symbol: SymbolId, offset: u64) -> write::Relocation {
let (encoding, size, addend, kind) = match target_info.architecture { let (encoding, size, addend, kind) = match target.architecture() {
roc_target::Architecture::Aarch32 => todo!(), roc_target::Architecture::Aarch32 => todo!(),
roc_target::Architecture::Aarch64 => { roc_target::Architecture::Aarch64 => {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
@ -957,7 +934,7 @@ fn build_proc<'a, B: Backend<'a>>(
proc: Proc<'a>, proc: Proc<'a>,
) { ) {
let mut local_data_index = 0; 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_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); let proc_offset = output.add_symbol_data(proc_id, section_id, &proc_data, 16);
for reloc in relocs.iter() { 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); add_undefined_rc_proc(output, name, &rc_proc_names);
if let Some(sym_id) = output.symbol_id(name.as_bytes()) { 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 { } else {
internal_error!("failed to find fn symbol for {:?}", name); internal_error!("failed to find fn symbol for {:?}", name);
} }

View file

@ -21,7 +21,7 @@ impl LlvmAlignment<'_> for IntWidth {
// 128-bit integers are not consistently represented by LLVM. // 128-bit integers are not consistently represented by LLVM.
// - AArch64 uses 16-byte alignment (https://godbolt.org/z/dYrfG5o4b) // - AArch64 uses 16-byte alignment (https://godbolt.org/z/dYrfG5o4b)
// - x86-64 uses 8-byte alignment (https://godbolt.org/z/qj5Mann6b) // - x86-64 uses 8-byte alignment (https://godbolt.org/z/qj5Mann6b)
let arch = interner.target_info().architecture; let arch = interner.target().architecture();
match arch { match arch {
Architecture::X86_64 => 8, Architecture::X86_64 => 8,
_ => 16, _ => 16,
@ -33,7 +33,7 @@ impl LlvmAlignment<'_> for IntWidth {
impl<'a> LlvmAlignment<'a> for FloatWidth { impl<'a> LlvmAlignment<'a> for FloatWidth {
fn llvm_alignment_bytes(&self, interner: &STLayoutInterner<'a>) -> u32 { 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 std::mem::align_of;
use Builtin::*; 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 // 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 // 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(_) Recursive(_)
| NullableWrapped { .. } | NullableWrapped { .. }
| NullableUnwrapped { .. } | 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), .llvm_alignment_bytes(interner),
Builtin(builtin) => builtin.llvm_alignment_bytes(interner), Builtin(builtin) => builtin.llvm_alignment_bytes(interner),
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) | Erased(_) => { RecursivePointer(_) | Ptr(_) | FunctionPointer(_) | Erased(_) => {
interner.target_info().ptr_width() as u32 interner.target().ptr_width() as u32
} }
} }
} }

View file

@ -37,7 +37,7 @@ pub fn call_bitcode_fn<'ctx>(
panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}") 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 // On windows zig uses a vector type <2xi64> instead of a i128 value
let vec_type = env.context.i64_type().vec_type(2); let vec_type = env.context.i64_type().vec_type(2);
if ret.get_type() == vec_type.into() { if ret.get_type() == vec_type.into() {
@ -70,7 +70,7 @@ fn call_bitcode_fn_help<'ctx>(
let it = args let it = args
.iter() .iter()
.map(|x| { .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() { if x.get_type() == env.context.i128_type().into() {
let parent = env let parent = env
.builder .builder
@ -1067,7 +1067,7 @@ pub(crate) fn call_str_bitcode_fn<'ctx>(
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use roc_target::Architecture::*; use roc_target::Architecture::*;
match env.target_info.architecture { match env.target.architecture() {
Aarch32 | X86_32 => { Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> = let mut arguments: Vec<BasicValueEnum> =
Vec::with_capacity_in(other_arguments.len() + 2 * strings.len(), env.arena); 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 bumpalo::collections::Vec;
use roc_target::Architecture::*; use roc_target::Architecture::*;
match env.target_info.architecture { match env.target.architecture() {
Aarch32 | X86_32 => { Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> = let mut arguments: Vec<BasicValueEnum> =
Vec::with_capacity_in(other_arguments.len() + 2 * lists.len(), env.arena); Vec::with_capacity_in(other_arguments.len() + 2 * lists.len(), env.arena);

View file

@ -52,10 +52,9 @@ use roc_mono::layout::{
RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout, RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout,
}; };
use roc_std::RocDec; use roc_std::RocDec;
use roc_target::{PtrWidth, TargetInfo}; use roc_target::{PtrWidth, Target};
use std::convert::TryInto; use std::convert::TryInto;
use std::path::Path; use std::path::Path;
use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple};
use super::convert::{struct_type_from_union_layout, RocUnion}; use super::convert::{struct_type_from_union_layout, RocUnion};
use super::intrinsics::{ use super::intrinsics::{
@ -737,7 +736,7 @@ pub struct Env<'a, 'ctx, 'env> {
pub compile_unit: &'env DICompileUnit<'ctx>, pub compile_unit: &'env DICompileUnit<'ctx>,
pub module: &'ctx Module<'ctx>, pub module: &'ctx Module<'ctx>,
pub interns: Interns, pub interns: Interns,
pub target_info: TargetInfo, pub target: Target,
pub mode: LlvmBackendMode, pub mode: LlvmBackendMode,
pub exposed_to_host: MutSet<Symbol>, pub exposed_to_host: MutSet<Symbol>,
} }
@ -750,7 +749,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
pub fn ptr_int(&self) -> IntType<'ctx> { pub fn ptr_int(&self) -> IntType<'ctx> {
let ctx = self.context; 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::Bytes4 => ctx.i32_type(),
roc_target::PtrWidth::Bytes8 => ctx.i64_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> { pub fn twice_ptr_int(&self) -> IntType<'ctx> {
let ctx = self.context; 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::Bytes4 => ctx.i64_type(),
roc_target::PtrWidth::Bytes8 => ctx.i128_type(), roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
} }
} }
pub fn small_str_bytes(&self) -> u32 { 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( pub fn build_intrinsic_call(
@ -872,7 +871,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
) -> CallSiteValue<'ctx> { ) -> CallSiteValue<'ctx> {
let false_val = self.context.bool_type().const_int(0, false); 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::Bytes8 => LLVM_MEMSET_I64,
roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32, roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32,
}; };
@ -932,7 +931,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
string: BasicValueEnum<'ctx>, string: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
match env.target_info.ptr_width() { match env.target.ptr_width() {
PtrWidth::Bytes4 => { PtrWidth::Bytes4 => {
// we need to pass the string by reference, but we currently hold the value. // we need to pass the string by reference, but we currently hold the value.
let alloca = env let alloca = env
@ -1011,48 +1010,29 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
} }
pub fn module_from_builtins<'ctx>( pub fn module_from_builtins<'ctx>(
target: &target_lexicon::Triple, target: Target,
ctx: &'ctx Context, ctx: &'ctx Context,
module_name: &str, module_name: &str,
) -> Module<'ctx> { ) -> Module<'ctx> {
// In the build script for the builtins module, we compile the builtins into LLVM bitcode // 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") include_bytes!("../../../builtins/bitcode/zig-out/builtins-host.bc")
} else { } else {
match target { match target {
Triple { Target::Wasm32 => {
architecture: Architecture::Wasm32,
..
} => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-wasm32.bc") include_bytes!("../../../builtins/bitcode/zig-out/builtins-wasm32.bc")
} }
Triple { Target::LinuxX32 => {
architecture: Architecture::X86_32(_),
operating_system: OperatingSystem::Linux,
..
} => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86.bc") include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86.bc")
} }
Triple { Target::LinuxX64 => {
architecture: Architecture::X86_64,
operating_system: OperatingSystem::Linux,
..
} => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86_64.bc") include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86_64.bc")
} }
Triple { Target::LinuxArm64 => {
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
operating_system: OperatingSystem::Linux,
..
} => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-aarch64.bc") include_bytes!("../../../builtins/bitcode/zig-out/builtins-aarch64.bc")
} }
Triple { Target::WinX64 => {
architecture: Architecture::X86_64,
operating_system: OperatingSystem::Windows,
..
} => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-windows-x86_64.bc") include_bytes!("../../../builtins/bitcode/zig-out/builtins-windows-x86_64.bc")
} }
_ => panic!("The zig builtins are not currently built for this target: {target:?}"), _ => 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); 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 => { PtrWidth::Bytes4 => {
env.builder env.builder
.new_build_load(zig_str_type(env), alloca, "load_const_str") .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>, parent: FunctionValue<'ctx>,
str_literal: &str, str_literal: &str,
) -> PointerValue<'ctx> { ) -> 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]; 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> { 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]; 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( let refcount_ptr = PointerToRefcount::from_ptr_to_data(
env, 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) tag_pointer_clear_tag_id(env, tag_ptr)
} else { } else {
tag_ptr tag_ptr
@ -1876,7 +1856,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data( let refcount_ptr = PointerToRefcount::from_ptr_to_data(
env, 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) tag_pointer_clear_tag_id(env, tag_ptr)
} else { } else {
tag_ptr tag_ptr
@ -2261,7 +2241,7 @@ fn build_wrapped_tag<'a, 'ctx>(
); );
let struct_type = env.context.struct_type(&field_types, false); 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( let tag_id_ptr = builder.new_build_struct_gep(
union_struct_type, union_struct_type,
raw_data_ptr, raw_data_ptr,
@ -2556,7 +2536,7 @@ fn tag_pointer_set_tag_id<'ctx>(
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> 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) // 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); 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") .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) { pub fn tag_pointer_tag_id_bits_and_mask(target: Target) -> (u64, u64) {
match target_info.ptr_width() { match target.ptr_width() {
roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111), roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111),
roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011), roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011),
} }
@ -2591,7 +2571,7 @@ pub fn tag_pointer_read_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> IntValue<'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 ptr_int = env.ptr_int();
let as_int = env.builder.new_build_ptr_to_int(pointer, ptr_int, "to_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, '_>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> 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 let as_int = env
.builder .builder
@ -2725,7 +2705,7 @@ pub fn get_tag_id<'a, 'ctx>(
UnionLayout::Recursive(_) => { UnionLayout::Recursive(_) => {
let argument_ptr = argument.into_pointer_value(); 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) get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
} else { } else {
tag_pointer_read_tag_id(env, argument_ptr) 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); 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) get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
} else { } else {
tag_pointer_read_tag_id(env, argument_ptr) 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>, union_layout: UnionLayout<'a>,
fields: &[&[InLayout<'a>]], fields: &[&[InLayout<'a>]],
) -> PointerValue<'ctx> { ) -> 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) { let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) {
RocUnion::tagged_from_slices(layout_interner, env.context, fields) 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 size = list_length * element_width as usize;
let alignment = layout_interner let alignment = layout_interner
.alignment_bytes(element_layout) .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 mut is_all_constant = true;
let zero_elements = 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 // runtime-evaluated elements
let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena); 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() { if value.is_pointer_value() {
let clear_tag_id = match other_layout { let clear_tag_id = match other_layout {
LayoutRepr::Union(union_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, _ => false,
}; };
@ -3562,7 +3542,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
let value = value.into_pointer_value(); let value = value.into_pointer_value();
let clear_tag_id = match layout_interner.runtime_representation(layout) { 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, _ => false,
}; };
@ -3640,7 +3620,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
if env.mode.runs_expects() { if env.mode.runs_expects() {
bd.position_at_end(throw_block); bd.position_at_end(throw_block);
match env.target_info.ptr_width() { match env.target.ptr_width() {
roc_target::PtrWidth::Bytes8 => { roc_target::PtrWidth::Bytes8 => {
let shared_memory = SharedMemoryPointer::get(env); let shared_memory = SharedMemoryPointer::get(env);
@ -3712,7 +3692,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
if env.mode.runs_expects() { if env.mode.runs_expects() {
bd.position_at_end(throw_block); bd.position_at_end(throw_block);
match env.target_info.ptr_width() { match env.target.ptr_width() {
roc_target::PtrWidth::Bytes8 => { roc_target::PtrWidth::Bytes8 => {
let shared_memory = SharedMemoryPointer::get(env); 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 // On x86_*, Modify the argument to specify it is passed by value and nonnull
// Aarch*, just passes in the pointer directly. // Aarch*, just passes in the pointer directly.
if matches!( if matches!(
env.target_info.architecture, env.target.architecture(),
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64 roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
) { ) {
let c_abi_type = match layout_interner.get_repr(*layout) { 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> { 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::Bytes4 => env.context.i32_type(),
PtrWidth::Bytes8 => env.context.i64_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. // The following three words are available for use in a target-specific manner.
// //
// So, let's create a 5-word buffer. // 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 // Due to https://github.com/llvm/llvm-project/issues/72908
// on windows, we store the register contents into this buffer directly! // on windows, we store the register contents into this buffer directly!
30 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> { pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
let jmp_buf = get_sjlj_buffer(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 // 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) 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 // 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) call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_WINDOWS_SETJMP)
} else { } else {
@ -6770,10 +6750,14 @@ pub fn to_cc_return<'a>(
layout: InLayout<'a>, layout: InLayout<'a>,
) -> CCReturn { ) -> CCReturn {
let return_size = layout_interner.stack_size(layout); let return_size = layout_interner.stack_size(layout);
let pass_result_by_pointer = match env.target_info.operating_system { // TODO: loop back and update this. It actually cares about the full abi (arch + os)
roc_target::OperatingSystem::Windows => return_size > env.target_info.ptr_width() as u32, let pass_result_by_pointer = match env.target.operating_system() {
roc_target::OperatingSystem::Unix => return_size > 2 * env.target_info.ptr_width() as u32, roc_target::OperatingSystem::Windows => return_size > env.target.ptr_width() as u32,
roc_target::OperatingSystem::Wasi => return_size > 2 * env.target_info.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 { if return_size == 0 {
@ -6996,7 +6980,7 @@ fn define_global_str_literal_ptr<'ctx>(
ptr, ptr,
&[env &[env
.ptr_int() .ptr_int()
.const_int(env.target_info.ptr_width() as u64, false)], .const_int(env.target.ptr_width() as u64, false)],
"get_rc_ptr", "get_rc_ptr",
) )
}; };
@ -7026,11 +7010,11 @@ fn define_global_str_literal<'ctx>(
Some(current) => current, Some(current) => current,
None => { 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); let mut bytes = Vec::with_capacity_in(size, env.arena);
// insert NULL bytes for the refcount // 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()); 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 // strings are NULL-terminated, which means we can't store the refcount (which is 8
// NULL bytes) // NULL bytes)
global.set_constant(true); 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_unnamed_addr(true);
global.set_linkage(inkwell::module::Linkage::Private); global.set_linkage(inkwell::module::Linkage::Private);

View file

@ -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 // 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. // its alignment is bigger than that of a list.
let element_align = layout_interner.alignment_bytes(element_layout); 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 { let fields = if element_first {
[element_layout, Layout::LIST_U8 /* any list works */] [element_layout, Layout::LIST_U8 /* any list works */]

View file

@ -11,7 +11,7 @@ use roc_mono::layout::{
round_up_to_alignment, Builtin, FunctionPointer, InLayout, Layout, LayoutInterner, LayoutRepr, round_up_to_alignment, Builtin, FunctionPointer, InLayout, Layout, LayoutInterner, LayoutRepr,
STLayoutInterner, UnionLayout, STLayoutInterner, UnionLayout,
}; };
use roc_target::TargetInfo; use roc_target::Target;
use super::struct_::RocStruct; use super::struct_::RocStruct;
@ -106,7 +106,7 @@ pub fn struct_type_from_union_layout<'a, 'ctx>(
| NullableWrapped { | NullableWrapped {
other_tags: tags, .. 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() RocUnion::tagged_from_slices(layout_interner, env.context, tags).struct_type()
} else { } else {
RocUnion::untagged_from_slices(layout_interner, env.context, tags).struct_type() 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 /// The int type that the C ABI turns our RocList/RocStr into
pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> { pub fn str_list_int(ctx: &Context, target: Target) -> IntType<'_> {
match target_info.ptr_width() { match target.ptr_width() {
roc_target::PtrWidth::Bytes4 => ctx.i64_type(), roc_target::PtrWidth::Bytes4 => ctx.i64_type(),
roc_target::PtrWidth::Bytes8 => ctx.i128_type(), roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
} }

View file

@ -184,8 +184,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>(
let after_header = offset; let after_header = offset;
let space_for_offsets = env.ptr_int().const_int( let space_for_offsets = env.ptr_int().const_int(
(lookups.len() * env.target_info.ptr_size() + lookups.len() * std::mem::size_of::<u32>()) (lookups.len() * env.target.ptr_size() + lookups.len() * std::mem::size_of::<u32>()) as _,
as _,
false, false,
); );
@ -232,9 +231,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>(
{ {
build_copy(env, original_ptr, offset, lookup_start.into()); build_copy(env, original_ptr, offset, lookup_start.into());
let ptr_width = env let ptr_width = env.ptr_int().const_int(env.target.ptr_size() as _, false);
.ptr_int()
.const_int(env.target_info.ptr_size() as _, false);
offset = env.builder.new_build_int_add(offset, ptr_width, "offset"); 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 tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
let layout = LayoutRepr::struct_(field_layouts); 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 layout
} else { } else {
// [...fields, tag ID] // [...fields, tag ID]
@ -914,7 +911,7 @@ fn write_pointer_with_tag_id<'a, 'ctx>(
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
tag_id: usize, 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 // first, store tag id as u32
let tag_id_intval = env.context.i32_type().const_int(tag_id as _, false); let tag_id_intval = env.context.i32_type().const_int(tag_id as _, false);
build_copy(env, ptr, offset, tag_id_intval.into()); build_copy(env, ptr, offset, tag_id_intval.into());

View file

@ -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 => { roc_target::OperatingSystem::Windows => {
// We don't need these functions on 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 // 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, roc_target::PtrWidth::Bytes4 => roc_str_arg,
// On 64-bit we pass RocStrs by reference internally // On 64-bit we pass RocStrs by reference internally
roc_target::PtrWidth::Bytes8 => { roc_target::PtrWidth::Bytes8 => {
@ -315,12 +315,12 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
pub fn build_longjmp_call(env: &Env) { pub fn build_longjmp_call(env: &Env) {
let jmp_buf = get_sjlj_buffer(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 // 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 tag = env.context.i32_type().const_int(1, false);
let _call = let _call =
call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP); 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 tag = env.context.i32_type().const_int(1, false);
let _call = call_void_bitcode_fn( let _call = call_void_bitcode_fn(
env, env,

View file

@ -20,7 +20,7 @@ use roc_mono::{
}, },
list_element_layout, list_element_layout,
}; };
use roc_target::{PtrWidth, TargetInfo}; use roc_target::{PtrWidth, Target};
use crate::llvm::{ use crate::llvm::{
bitcode::{ bitcode::{
@ -129,7 +129,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Str.joinWith : List Str, Str -> Str // Str.joinWith : List Str, Str -> Str
arguments!(list, string); arguments!(list, string);
match env.target_info.ptr_width() { match env.target.ptr_width() {
PtrWidth::Bytes4 => { PtrWidth::Bytes4 => {
// list and string are both stored as structs on the stack on 32-bit targets // list and string are both stored as structs on the stack on 32-bit targets
call_str_bitcode_fn( call_str_bitcode_fn(
@ -197,7 +197,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
}; };
use roc_target::Architecture::*; use roc_target::Architecture::*;
let result = match env.target_info.architecture { let result = match env.target.architecture() {
Aarch32 | X86_32 => { Aarch32 | X86_32 => {
let zig_function = env.module.get_function(intrinsic).unwrap(); let zig_function = env.module.get_function(intrinsic).unwrap();
let zig_function_type = zig_function.get_type(); let zig_function_type = zig_function.get_type();
@ -283,14 +283,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
}; };
use roc_target::OperatingSystem::*; 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 => { Windows => {
// there is just one return register on 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 // 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"); .new_build_alloca(result_type, "alloca_utf8_validate_bytes_result");
use roc_target::Architecture::*; use roc_target::Architecture::*;
match env.target_info.architecture { match env.target.architecture() {
Aarch32 | X86_32 => { Aarch32 | X86_32 => {
arguments!(list); arguments!(list);
let (a, b) = pass_list_or_string_to_zig_32bit(env, list.into_struct_value()); 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) { let value_ptr = match layout_interner.runtime_representation(data_layout) {
LayoutRepr::Union(union_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) 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> { fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*; use roc_target::Architecture::*;
use roc_target::OperatingSystem::*; use roc_target::OperatingSystem::*;
match env.target_info.operating_system { match env.target.operating_system() {
Windows => { Windows => {
let dec_type = zig_dec_type(env); let dec_type = zig_dec_type(env);
@ -1917,8 +1917,8 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu
alloca.into() alloca.into()
} }
Unix => { Linux | Mac => {
if matches!(env.target_info.architecture, X86_32 | X86_64) { 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"); 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(); let i64_type = env.context.i64_type();
@ -1937,21 +1937,15 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu
env.builder env.builder
.new_build_load(i64_type.array_type(2), alloca, "load as array") .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> { 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(); let dec = dec.into_int_value();
match env.target_info { match env.target {
TargetInfo { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (low, high) = dec_split_into_words(env, dec); let (low, high) = dec_split_into_words(env, dec);
call_str_bitcode_fn( call_str_bitcode_fn(
@ -1962,10 +1956,7 @@ fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> Basic
bitcode::DEC_TO_STR, bitcode::DEC_TO_STR,
) )
} }
TargetInfo { Target::Wasm32 => call_str_bitcode_fn(
architecture: Wasm32,
operating_system: Unix,
} => call_str_bitcode_fn(
env, env,
&[], &[],
&[dec.into()], &[dec.into()],
@ -1987,22 +1978,13 @@ fn dec_unary_op<'ctx>(
fn_name: &str, fn_name: &str,
dec: BasicValueEnum<'ctx>, dec: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec = dec.into_int_value(); let dec = dec.into_int_value();
match env.target_info { match env.target {
TargetInfo { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (low, high) = dec_split_into_words(env, dec); let (low, high) = dec_split_into_words(env, dec);
call_bitcode_fn(env, &[low.into(), high.into()], fn_name) call_bitcode_fn(env, &[low.into(), high.into()], fn_name)
} }
TargetInfo { Target::Wasm32 => call_bitcode_fn(env, &[dec.into()], fn_name),
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[dec.into()], fn_name),
_ => call_bitcode_fn(env, &[dec_alloca(env, dec)], fn_name), _ => call_bitcode_fn(env, &[dec_alloca(env, dec)], fn_name),
} }
} }
@ -2013,17 +1995,11 @@ fn dec_binary_op<'ctx>(
dec1: BasicValueEnum<'ctx>, dec1: BasicValueEnum<'ctx>,
dec2: BasicValueEnum<'ctx>, dec2: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec1 = dec1.into_int_value(); let dec1 = dec1.into_int_value();
let dec2 = dec2.into_int_value(); let dec2 = dec2.into_int_value();
match env.target_info { match env.target {
TargetInfo { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (low1, high1) = dec_split_into_words(env, dec1); let (low1, high1) = dec_split_into_words(env, dec1);
let (low2, high2) = dec_split_into_words(env, dec2); let (low2, high2) = dec_split_into_words(env, dec2);
let lowr_highr = call_bitcode_fn( let lowr_highr = call_bitcode_fn(
@ -2043,10 +2019,7 @@ fn dec_binary_op<'ctx>(
.build_load(env.context.i128_type(), ptr, "to_i128") .build_load(env.context.i128_type(), ptr, "to_i128")
.unwrap() .unwrap()
} }
TargetInfo { Target::Wasm32 => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name),
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name),
_ => call_bitcode_fn( _ => call_bitcode_fn(
env, env,
&[dec_alloca(env, dec1), dec_alloca(env, dec2)], &[dec_alloca(env, dec1), dec_alloca(env, dec2)],
@ -2061,20 +2034,14 @@ fn dec_binop_with_overflow<'ctx>(
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let lhs = lhs.into_int_value(); let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value(); let rhs = rhs.into_int_value();
let return_type = zig_with_overflow_roc_dec(env); let return_type = zig_with_overflow_roc_dec(env);
let return_alloca = env.builder.new_build_alloca(return_type, "return_alloca"); let return_alloca = env.builder.new_build_alloca(return_type, "return_alloca");
match env.target_info { match env.target {
TargetInfo { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs); let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs); let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_void_bitcode_fn( call_void_bitcode_fn(
@ -2089,10 +2056,7 @@ fn dec_binop_with_overflow<'ctx>(
fn_name, fn_name,
); );
} }
TargetInfo { Target::Wasm32 => {
architecture: Wasm32,
operating_system: Unix,
} => {
call_void_bitcode_fn( call_void_bitcode_fn(
env, env,
&[return_alloca.into(), lhs.into(), rhs.into()], &[return_alloca.into(), lhs.into(), rhs.into()],
@ -2123,17 +2087,11 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let lhs = lhs.into_int_value(); let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value(); let rhs = rhs.into_int_value();
match env.target_info { match env.target {
TargetInfo { Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs); let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs); let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_bitcode_fn( call_bitcode_fn(
@ -2147,10 +2105,7 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
fn_name, fn_name,
) )
} }
TargetInfo { Target::Wasm32 => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name),
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name),
_ => call_bitcode_fn(env, &[dec_alloca(env, lhs), dec_alloca(env, rhs)], 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] &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 => { PtrWidth::Bytes4 => {
let zig_function = env.module.get_function(intrinsic).unwrap(); let zig_function = env.module.get_function(intrinsic).unwrap();
let zig_function_type = zig_function.get_type(); let zig_function_type = zig_function.get_type();
@ -2489,12 +2444,11 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
} }
PtrWidth::Bytes8 => { PtrWidth::Bytes8 => {
let return_by_pointer = { let return_by_pointer = {
if env.target_info.operating_system if env.target.operating_system() == roc_target::OperatingSystem::Windows
== 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 { } 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 { if return_by_pointer {

View file

@ -80,7 +80,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> { pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> {
let current = self.get_refcount(env); 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 => { roc_target::PtrWidth::Bytes4 => {
env.context.i32_type().const_int(i32::MIN as u64, false) env.context.i32_type().const_int(i32::MIN as u64, false)
} }
@ -128,7 +128,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
) { ) {
let alignment = layout let alignment = layout
.allocation_alignment_bytes(layout_interner) .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 context = env.context;
let block = env.builder.get_insert_block().expect("to be in a function"); 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 // 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 // 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 Linkage::External
} else { } else {
Linkage::Private Linkage::Private
@ -1162,7 +1162,7 @@ fn build_rec_union_help<'a, 'ctx>(
debug_assert!(arg_val.is_pointer_value()); debug_assert!(arg_val.is_pointer_value());
let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val); 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()) tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
} else { } else {
arg_val.into_pointer_value() arg_val.into_pointer_value()

View file

@ -31,8 +31,7 @@ use crate::layout::{ReturnMethod, WasmLayout};
use crate::low_level::{call_higher_order_lowlevel, LowLevelCall}; use crate::low_level::{call_higher_order_lowlevel, LowLevelCall};
use crate::storage::{AddressValue, Storage, StoredValue, StoredVarKind}; use crate::storage::{AddressValue, Storage, StoredValue, StoredVarKind};
use crate::{ use crate::{
copy_memory, CopyMemoryConfig, Env, DEBUG_SETTINGS, MEMORY_NAME, PTR_SIZE, PTR_TYPE, copy_memory, CopyMemoryConfig, Env, DEBUG_SETTINGS, MEMORY_NAME, PTR_SIZE, PTR_TYPE, TARGET,
TARGET_INFO,
}; };
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -1651,8 +1650,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
return; return;
} }
let stores_tag_id_as_data = union_layout.stores_tag_id_as_data(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_INFO); let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET);
let (data_size, data_alignment) = let (data_size, data_alignment) =
union_layout.data_size_and_alignment(self.layout_interner); 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_offset = union_layout.tag_id_offset(self.layout_interner).unwrap();
let id_align = union_layout.discriminant().alignment_bytes(); 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), U0 | U1 | U8 => self.code_builder.i32_load8_u(id_align, id_offset),
U16 => self.code_builder.i32_load16_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 self.storage
.load_symbols(&mut self.code_builder, &[structure]); .load_symbols(&mut self.code_builder, &[structure]);
self.code_builder.i32_const(3); self.code_builder.i32_const(3);
@ -1847,7 +1846,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
StoredValue::Local { local_id, .. } => (local_id, 0), 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 { let from_addr_val = if stores_tag_id_in_pointer {
self.code_builder.get_local(tag_local_id); 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), 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; let from_offset = tag_offset + field_offset;

View file

@ -18,16 +18,16 @@ use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp; use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::ir::{Proc, ProcLayout}; use roc_mono::ir::{Proc, ProcLayout};
use roc_mono::layout::{LayoutIds, STLayoutInterner}; use roc_mono::layout::{LayoutIds, STLayoutInterner};
use roc_target::TargetInfo; use roc_target::Target;
use roc_wasm_module::parse::ParseError; use roc_wasm_module::parse::ParseError;
use roc_wasm_module::{Align, LocalId, ValueType, WasmModule}; use roc_wasm_module::{Align, LocalId, ValueType, WasmModule};
use crate::backend::{ProcLookupData, ProcSource, WasmBackend}; use crate::backend::{ProcLookupData, ProcSource, WasmBackend};
use crate::code_builder::CodeBuilder; use crate::code_builder::CodeBuilder;
const TARGET_INFO: TargetInfo = TargetInfo::default_wasm32(); const TARGET: Target = Target::Wasm32;
const PTR_SIZE: u32 = { 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 // const assert that our pointer width is actually 4
// the code relies on the pointer width being exactly 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_to_app_map,
host_module, host_module,
fn_index_offset, 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 { if DEBUG_SETTINGS.user_procs_ir {

View file

@ -67,7 +67,8 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
let arena = Bump::new(); let arena = Bump::new();
let cwd = std::env::current_dir().unwrap(); let cwd = std::env::current_dir().unwrap();
let source = roc_builtins::roc::module_source(module_id); 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 function_kind = roc_solve::FunctionKind::LambdaSet;
let res_module = roc_load_internal::file::load_and_typecheck_str( 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, source,
cwd, cwd,
Default::default(), Default::default(),
target_info, target,
function_kind, function_kind,
roc_reporting::report::RenderTarget::ColorTerminal, roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE, roc_reporting::report::DEFAULT_PALETTE,

View file

@ -6,7 +6,7 @@ use roc_collections::all::MutMap;
use roc_module::symbol::ModuleId; use roc_module::symbol::ModuleId;
use roc_packaging::cache::RocCacheDir; use roc_packaging::cache::RocCacheDir;
use roc_reporting::report::{Palette, RenderTarget}; use roc_reporting::report::{Palette, RenderTarget};
use roc_target::TargetInfo; use roc_target::Target;
use std::path::PathBuf; use std::path::PathBuf;
const SKIP_SUBS_CACHE: bool = { const SKIP_SUBS_CACHE: bool = {
@ -51,7 +51,7 @@ fn load<'a>(
pub fn load_single_threaded<'a>( pub fn load_single_threaded<'a>(
arena: &'a Bump, arena: &'a Bump,
load_start: LoadStart<'a>, load_start: LoadStart<'a>,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
render: RenderTarget, render: RenderTarget,
palette: Palette, palette: Palette,
@ -65,7 +65,7 @@ pub fn load_single_threaded<'a>(
arena, arena,
load_start, load_start,
exposed_types, exposed_types,
target_info, target,
function_kind, function_kind,
cached_subs, cached_subs,
render, render,
@ -172,7 +172,7 @@ pub fn load_and_typecheck_str<'a>(
filename: PathBuf, filename: PathBuf,
source: &'a str, source: &'a str,
src_dir: PathBuf, src_dir: PathBuf,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
render: RenderTarget, render: RenderTarget,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
@ -188,7 +188,7 @@ pub fn load_and_typecheck_str<'a>(
match load_single_threaded( match load_single_threaded(
arena, arena,
load_start, load_start,
target_info, target,
function_kind, function_kind,
render, render,
palette, palette,

View file

@ -123,7 +123,7 @@ mod test_reporting {
let mut file = File::create(file_path).unwrap(); let mut file = File::create(file_path).unwrap();
writeln!(file, "{module_src}").unwrap(); writeln!(file, "{module_src}").unwrap();
let load_config = LoadConfig { let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(), target: roc_target::Target::LinuxX64,
render: RenderTarget::Generic, render: RenderTarget::Generic,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
threading: Threading::Single, threading: Threading::Single,

View file

@ -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::module::{extract_module_owned_implementations, SolveConfig, Solved, SolvedModule};
use roc_solve::FunctionKind; use roc_solve::FunctionKind;
use roc_solve_problem::TypeError; 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::subs::{CopiedImport, ExposedTypesStorageSubs, Subs, VarStore, Variable};
use roc_types::types::{Alias, Types}; use roc_types::types::{Alias, Types};
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
@ -104,7 +104,7 @@ macro_rules! log {
#[derive(Debug)] #[derive(Debug)]
pub struct LoadConfig { pub struct LoadConfig {
pub target_info: TargetInfo, pub target: Target,
pub render: RenderTarget, pub render: RenderTarget,
pub palette: Palette, pub palette: Palette,
pub threading: Threading, pub threading: Threading,
@ -453,7 +453,7 @@ fn start_phase<'a>(
Subs::default(), Subs::default(),
None, // no expectations for derived module None, // no expectations for derived module
ProcsBase::default(), ProcsBase::default(),
LayoutCache::new(state.layout_interner.fork(), state.target_info), LayoutCache::new(state.layout_interner.fork(), state.target),
ModuleTiming::new(Instant::now()), ModuleTiming::new(Instant::now()),
) )
} else if state.make_specializations_pass.current_pass() == 1 { } else if state.make_specializations_pass.current_pass() == 1 {
@ -512,7 +512,7 @@ fn start_phase<'a>(
&mut ident_ids, &mut ident_ids,
&state.derived_module, &state.derived_module,
&mut module_timing, &mut module_timing,
state.target_info, state.target,
&state.exposed_types, &state.exposed_types,
&mut procs_base, &mut procs_base,
&mut state.world_abilities, &mut state.world_abilities,
@ -691,7 +691,7 @@ struct State<'a> {
pub platform_data: Option<PlatformData<'a>>, pub platform_data: Option<PlatformData<'a>>,
pub exposed_types: ExposedByModule, pub exposed_types: ExposedByModule,
pub platform_path: PlatformPath<'a>, pub platform_path: PlatformPath<'a>,
pub target_info: TargetInfo, pub target: Target,
pub(self) function_kind: FunctionKind, pub(self) function_kind: FunctionKind,
/// Note: only packages and platforms actually expose any modules; /// Note: only packages and platforms actually expose any modules;
@ -755,7 +755,7 @@ impl<'a> State<'a> {
root_id: ModuleId, root_id: ModuleId,
root_path: PathBuf, root_path: PathBuf,
opt_platform_shorthand: Option<&'a str>, opt_platform_shorthand: Option<&'a str>,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>, arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
@ -776,7 +776,7 @@ impl<'a> State<'a> {
root_subs: None, root_subs: None,
opt_platform_shorthand, opt_platform_shorthand,
cache_dir, cache_dir,
target_info, target,
function_kind, function_kind,
platform_data: None, platform_data: None,
platform_path: PlatformPath::NotSpecified, platform_path: PlatformPath::NotSpecified,
@ -803,7 +803,7 @@ impl<'a> State<'a> {
exec_mode, exec_mode,
make_specializations_pass: MakeSpecializationsPass::Pass(1), make_specializations_pass: MakeSpecializationsPass::Pass(1),
world_abilities: Default::default(), 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, source: &'a str,
src_dir: PathBuf, src_dir: PathBuf,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
render: RenderTarget, render: RenderTarget,
palette: Palette, palette: Palette,
@ -1049,7 +1049,7 @@ pub fn load_and_typecheck_str<'a>(
let cached_subs = MutMap::default(); let cached_subs = MutMap::default();
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
render, render,
palette, palette,
threading, threading,
@ -1317,7 +1317,7 @@ pub fn load<'a>(
arena, arena,
load_start, load_start,
exposed_types, exposed_types,
load_config.target_info, load_config.target,
load_config.function_kind, load_config.function_kind,
cached_types, cached_types,
load_config.render, load_config.render,
@ -1329,7 +1329,7 @@ pub fn load<'a>(
arena, arena,
load_start, load_start,
exposed_types, exposed_types,
load_config.target_info, load_config.target,
load_config.function_kind, load_config.function_kind,
cached_types, cached_types,
load_config.render, load_config.render,
@ -1346,7 +1346,7 @@ pub fn load_single_threaded<'a>(
arena: &'a Bump, arena: &'a Bump,
load_start: LoadStart<'a>, load_start: LoadStart<'a>,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
cached_types: MutMap<ModuleId, TypeState>, cached_types: MutMap<ModuleId, TypeState>,
render: RenderTarget, render: RenderTarget,
@ -1376,7 +1376,7 @@ pub fn load_single_threaded<'a>(
root_id, root_id,
root_path, root_path,
opt_platform_shorthand, opt_platform_shorthand,
target_info, target,
function_kind, function_kind,
exposed_types, exposed_types,
arc_modules, arc_modules,
@ -1427,7 +1427,7 @@ pub fn load_single_threaded<'a>(
&msg_tx, &msg_tx,
&src_dir, &src_dir,
roc_cache_dir, roc_cache_dir,
target_info, target,
); );
match control_flow { match control_flow {
@ -1672,7 +1672,7 @@ fn load_multi_threaded<'a>(
arena: &'a Bump, arena: &'a Bump,
load_start: LoadStart<'a>, load_start: LoadStart<'a>,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
cached_types: MutMap<ModuleId, TypeState>, cached_types: MutMap<ModuleId, TypeState>,
render: RenderTarget, render: RenderTarget,
@ -1718,7 +1718,7 @@ fn load_multi_threaded<'a>(
root_id, root_id,
root_path, root_path,
opt_platform_shorthand, opt_platform_shorthand,
target_info, target,
function_kind, function_kind,
exposed_types, exposed_types,
arc_modules, arc_modules,
@ -1794,7 +1794,7 @@ fn load_multi_threaded<'a>(
msg_tx, msg_tx,
src_dir, src_dir,
roc_cache_dir, roc_cache_dir,
target_info, target,
) )
}); });
@ -1923,7 +1923,7 @@ fn worker_task_step<'a>(
msg_tx: &MsgSender<'a>, msg_tx: &MsgSender<'a>,
src_dir: &Path, src_dir: &Path,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
target_info: TargetInfo, target: Target,
) -> Result<ControlFlow<(), ()>, LoadingProblem<'a>> { ) -> Result<ControlFlow<(), ()>, LoadingProblem<'a>> {
match worker_msg_rx.try_recv() { match worker_msg_rx.try_recv() {
Ok(msg) => { Ok(msg) => {
@ -1952,7 +1952,7 @@ fn worker_task_step<'a>(
src_dir, src_dir,
msg_tx.clone(), msg_tx.clone(),
roc_cache_dir, roc_cache_dir,
target_info, target,
); );
match result { match result {
@ -1997,7 +1997,7 @@ fn worker_task<'a>(
msg_tx: MsgSender<'a>, msg_tx: MsgSender<'a>,
src_dir: &Path, src_dir: &Path,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
target_info: TargetInfo, target: Target,
) -> Result<(), LoadingProblem<'a>> { ) -> Result<(), LoadingProblem<'a>> {
// Keep listening until we receive a Shutdown msg // Keep listening until we receive a Shutdown msg
for msg in worker_msg_rx.iter() { for msg in worker_msg_rx.iter() {
@ -2051,7 +2051,7 @@ fn worker_task<'a>(
src_dir, src_dir,
msg_tx.clone(), msg_tx.clone(),
roc_cache_dir, roc_cache_dir,
target_info, target,
); );
match result { match result {
@ -2720,7 +2720,7 @@ fn update<'a>(
if state.goal_phase() > Phase::SolveTypes || state.exec_mode.build_if_checks() { if state.goal_phase() > Phase::SolveTypes || state.exec_mode.build_if_checks() {
let layout_cache = state.layout_caches.pop().unwrap_or_else(|| { 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 { let typechecked = TypeCheckedModule {
@ -2948,7 +2948,7 @@ fn update<'a>(
} }
let layout_interner = { 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); std::mem::swap(&mut state.layout_interner, &mut taken);
taken taken
}; };
@ -3001,7 +3001,7 @@ fn update<'a>(
arena, arena,
&layout_interner, &layout_interner,
module_id, module_id,
state.target_info, state.target,
ident_ids, ident_ids,
&mut update_mode_ids, &mut update_mode_ids,
&mut state.procedures, &mut state.procedures,
@ -5676,7 +5676,7 @@ fn make_specializations<'a>(
mut layout_cache: LayoutCache<'a>, mut layout_cache: LayoutCache<'a>,
specializations_we_must_make: Vec<ExternalSpecializations<'a>>, specializations_we_must_make: Vec<ExternalSpecializations<'a>>,
mut module_timing: ModuleTiming, mut module_timing: ModuleTiming,
target_info: TargetInfo, target: Target,
world_abilities: WorldAbilities, world_abilities: WorldAbilities,
exposed_by_module: &ExposedByModule, exposed_by_module: &ExposedByModule,
derived_module: SharedDerivedModule, derived_module: SharedDerivedModule,
@ -5691,7 +5691,7 @@ fn make_specializations<'a>(
expectation_subs: expectations.as_mut().map(|e| &mut e.subs), expectation_subs: expectations.as_mut().map(|e| &mut e.subs),
home, home,
ident_ids: &mut ident_ids, ident_ids: &mut ident_ids,
target_info, target,
update_mode_ids: &mut update_mode_ids, update_mode_ids: &mut update_mode_ids,
// call_specialization_counter=0 is reserved // call_specialization_counter=0 is reserved
call_specialization_counter: 1, call_specialization_counter: 1,
@ -5762,7 +5762,7 @@ fn build_pending_specializations<'a>(
declarations: Declarations, declarations: Declarations,
mut module_timing: ModuleTiming, mut module_timing: ModuleTiming,
mut layout_cache: LayoutCache<'a>, mut layout_cache: LayoutCache<'a>,
target_info: TargetInfo, target: Target,
exposed_to_host: ExposedToHost, exposed_to_host: ExposedToHost,
exposed_by_module: &ExposedByModule, exposed_by_module: &ExposedByModule,
world_abilities: WorldAbilities, world_abilities: WorldAbilities,
@ -5791,7 +5791,7 @@ fn build_pending_specializations<'a>(
expectation_subs: expectations.as_mut().map(|e| &mut e.subs), expectation_subs: expectations.as_mut().map(|e| &mut e.subs),
home, home,
ident_ids: &mut ident_ids, ident_ids: &mut ident_ids,
target_info, target,
update_mode_ids: &mut update_mode_ids, update_mode_ids: &mut update_mode_ids,
// call_specialization_counter=0 is reserved // call_specialization_counter=0 is reserved
call_specialization_counter: 1, call_specialization_counter: 1,
@ -6241,7 +6241,7 @@ fn load_derived_partial_procs<'a>(
ident_ids: &mut IdentIds, ident_ids: &mut IdentIds,
derived_module: &SharedDerivedModule, derived_module: &SharedDerivedModule,
module_timing: &mut ModuleTiming, module_timing: &mut ModuleTiming,
target_info: TargetInfo, target: Target,
exposed_by_module: &ExposedByModule, exposed_by_module: &ExposedByModule,
procs_base: &mut ProcsBase<'a>, procs_base: &mut ProcsBase<'a>,
world_abilities: &mut WorldAbilities, world_abilities: &mut WorldAbilities,
@ -6272,7 +6272,7 @@ fn load_derived_partial_procs<'a>(
expectation_subs: None, expectation_subs: None,
home, home,
ident_ids, ident_ids,
target_info, target,
update_mode_ids: &mut update_mode_ids, update_mode_ids: &mut update_mode_ids,
// call_specialization_counter=0 is reserved // call_specialization_counter=0 is reserved
call_specialization_counter: 1, call_specialization_counter: 1,
@ -6346,7 +6346,7 @@ fn run_task<'a>(
src_dir: &Path, src_dir: &Path,
msg_tx: MsgSender<'a>, msg_tx: MsgSender<'a>,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
target_info: TargetInfo, target: Target,
) -> Result<(), LoadingProblem<'a>> { ) -> Result<(), LoadingProblem<'a>> {
use BuildTask::*; use BuildTask::*;
@ -6451,7 +6451,7 @@ fn run_task<'a>(
decls, decls,
module_timing, module_timing,
layout_cache, layout_cache,
target_info, target,
exposed_to_host, exposed_to_host,
&exposed_by_module, &exposed_by_module,
world_abilities, world_abilities,
@ -6480,7 +6480,7 @@ fn run_task<'a>(
layout_cache, layout_cache,
specializations_we_must_make, specializations_we_must_make,
module_timing, module_timing,
target_info, target,
world_abilities, world_abilities,
&exposed_by_module, &exposed_by_module,
derived_module, derived_module,

View file

@ -31,7 +31,7 @@ use roc_reporting::report::RocDocAllocator;
use roc_reporting::report::{can_problem, DEFAULT_PALETTE}; use roc_reporting::report::{can_problem, DEFAULT_PALETTE};
use roc_reporting::report::{strip_colors, RenderTarget}; use roc_reporting::report::{strip_colors, RenderTarget};
use roc_solve::FunctionKind; 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::name_and_print_var;
use roc_types::pretty_print::DebugPrint; use roc_types::pretty_print::DebugPrint;
use std::collections::HashMap; use std::collections::HashMap;
@ -41,7 +41,7 @@ fn load_and_typecheck(
arena: &Bump, arena: &Bump,
filename: PathBuf, filename: PathBuf,
exposed_types: ExposedByModule, exposed_types: ExposedByModule,
target_info: TargetInfo, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
) -> Result<LoadedModule, LoadingProblem> { ) -> Result<LoadedModule, LoadingProblem> {
use LoadResult::*; use LoadResult::*;
@ -54,7 +54,7 @@ fn load_and_typecheck(
DEFAULT_PALETTE, DEFAULT_PALETTE,
)?; )?;
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::Generic, render: RenderTarget::Generic,
palette: DEFAULT_PALETTE, 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 // HELPERS
@ -184,7 +184,7 @@ fn multiple_modules_help<'a>(
arena, arena,
full_file_path, full_file_path,
Default::default(), Default::default(),
TARGET_INFO, TARGET,
FunctionKind::LambdaSet, FunctionKind::LambdaSet,
) )
}; };
@ -204,7 +204,7 @@ fn load_fixture(
&arena, &arena,
filename, filename,
subs_by_module, subs_by_module,
TARGET_INFO, TARGET,
FunctionKind::LambdaSet, FunctionKind::LambdaSet,
); );
let mut loaded_module = match loaded { let mut loaded_module = match loaded {
@ -367,7 +367,7 @@ fn interface_with_deps() {
&arena, &arena,
filename, filename,
subs_by_module, subs_by_module,
TARGET_INFO, TARGET,
FunctionKind::LambdaSet, FunctionKind::LambdaSet,
); );

View file

@ -3,7 +3,7 @@ use bumpalo::collections::CollectIn;
use bumpalo::Bump; use bumpalo::Bump;
use roc_module::low_level::LowLevel; use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_target::TargetInfo; use roc_target::Target;
use crate::ir::{ use crate::ir::{
BranchInfo, Call, CallSpecId, CallType, Expr, JoinPointId, Literal, ModifyRc, PassedFunction, BranchInfo, Call, CallSpecId, CallType, Expr, JoinPointId, Literal, ModifyRc, PassedFunction,
@ -93,20 +93,20 @@ pub struct Context<'a> {
pub struct CodeGenHelp<'a> { pub struct CodeGenHelp<'a> {
arena: &'a Bump, arena: &'a Bump,
home: ModuleId, home: ModuleId,
target_info: TargetInfo, target: Target,
layout_isize: InLayout<'a>, layout_isize: InLayout<'a>,
specializations: Vec<'a, Specialization<'a>>, specializations: Vec<'a, Specialization<'a>>,
debug_recursion_depth: usize, debug_recursion_depth: usize,
} }
impl<'a> CodeGenHelp<'a> { impl<'a> CodeGenHelp<'a> {
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self { pub fn new(arena: &'a Bump, target: Target, home: ModuleId) -> Self {
let layout_isize = Layout::isize(target_info); let layout_isize = Layout::isize(target);
CodeGenHelp { CodeGenHelp {
arena, arena,
home, home,
target_info, target,
layout_isize, layout_isize,
specializations: Vec::with_capacity_in(16, arena), specializations: Vec::with_capacity_in(16, arena),
debug_recursion_depth: 0, debug_recursion_depth: 0,

View file

@ -383,7 +383,7 @@ pub fn refcount_reset_proc_body<'a>(
}; };
// Constant for unique refcount // 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::Bytes4 => i32::MIN as i128,
PtrWidth::Bytes8 => i64::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) { 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, _ => false,
}; };
@ -508,7 +508,7 @@ pub fn refcount_resetref_proc_body<'a>(
}; };
// Constant for unique refcount // 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::Bytes4 => i32::MIN as i128,
PtrWidth::Bytes8 => i64::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) { 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, _ => false,
}; };
@ -617,7 +617,7 @@ fn rc_ptr_from_data_ptr_help<'a>(
// Pointer size constant // Pointer size constant
let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size"); let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size");
let ptr_size_expr = Expr::Literal(Literal::Int( 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); 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]), 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 // Typecast the refcount address from integer to pointer
let cast_expr = Expr::Call(Call { let cast_expr = Expr::Call(Call {
@ -697,7 +697,7 @@ fn modify_refcount<'a>(
} }
HelperOp::Dec | HelperOp::DecRef(_) => { 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 { let (op, ptr) = match ptr {
Pointer::ToData(s) => (LowLevel::RefCountDecDataPtr, s), 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 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 = lowlevel NumLt length zero
let is_slice = root.create_symbol(ident_ids, "is_slice"); let is_slice = root.create_symbol(ident_ids, "is_slice");
@ -1032,7 +1032,7 @@ fn refcount_list<'a>(
// //
let alignment = Ord::max( let alignment = Ord::max(
root.target_info.ptr_width() as u32, root.target.ptr_width() as u32,
layout_interner.alignment_bytes(elem_layout), layout_interner.alignment_bytes(elem_layout),
); );

View file

@ -1181,7 +1181,7 @@ fn specialize_list<'a, 'i>(
newer_continuation = arena.alloc(Stmt::Let( newer_continuation = arena.alloc(Stmt::Let(
index_symbol, index_symbol,
Expr::Literal(Literal::Int(i128::to_ne_bytes(i as i128))), Expr::Literal(Literal::Int(i128::to_ne_bytes(i as i128))),
Layout::isize(layout_interner.target_info()), Layout::isize(layout_interner.target()),
index, index,
)); ));
} }

View file

@ -31,7 +31,7 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_problem::can::{RuntimeError, ShadowKind}; use roc_problem::can::{RuntimeError, ShadowKind};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
use roc_std::RocDec; use roc_std::RocDec;
use roc_target::TargetInfo; use roc_target::Target;
use roc_types::subs::{ use roc_types::subs::{
instantiate_rigids, storage_copy_var_to, Content, ExhaustiveMark, FlatType, RedundantMark, instantiate_rigids, storage_copy_var_to, Content, ExhaustiveMark, FlatType, RedundantMark,
StorageSubs, Subs, Variable, VariableSubsSlice, StorageSubs, Subs, Variable, VariableSubsSlice,
@ -1354,7 +1354,7 @@ pub struct Env<'a, 'i> {
pub expectation_subs: Option<&'i mut Subs>, pub expectation_subs: Option<&'i mut Subs>,
pub home: ModuleId, pub home: ModuleId,
pub ident_ids: &'i mut IdentIds, pub ident_ids: &'i mut IdentIds,
pub target_info: TargetInfo, pub target: Target,
pub update_mode_ids: &'i mut UpdateModeIds, pub update_mode_ids: &'i mut UpdateModeIds,
pub call_specialization_counter: u32, pub call_specialization_counter: u32,
// TODO: WorldAbilities and exposed_by_module share things, think about how to combine them // TODO: WorldAbilities and exposed_by_module share things, think about how to combine them

View file

@ -1779,7 +1779,7 @@ fn test_to_comparison<'a>(
let real_len = env.unique_symbol(); let real_len = env.unique_symbol();
let test_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((real_len, usize_layout, real_len_expr));
stores.push((test_len, usize_layout, test_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 len_symbol = env.unique_symbol();
let switch = Stmt::Switch { let switch = Stmt::Switch {
cond_layout: Layout::usize(env.target_info), cond_layout: Layout::usize(env.target),
cond_symbol: len_symbol, cond_symbol: len_symbol,
branches: branches.into_bump_slice(), branches: branches.into_bump_slice(),
default_branch: (default_branch_info, env.arena.alloc(default_branch)), default_branch: (default_branch_info, env.arena.alloc(default_branch)),
@ -2355,7 +2355,7 @@ fn decide_to_branching<'a>(
Stmt::Let( Stmt::Let(
len_symbol, len_symbol,
len_expr, len_expr,
Layout::usize(env.target_info), Layout::usize(env.target),
env.arena.alloc(switch), env.arena.alloc(switch),
) )
} else { } else {

View file

@ -10,7 +10,7 @@ use roc_error_macros::{internal_error, todo_abilities};
use roc_module::ident::{Lowercase, TagName}; use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::{Interns, Symbol}; use roc_module::symbol::{Interns, Symbol};
use roc_problem::can::RuntimeError; use roc_problem::can::RuntimeError;
use roc_target::{PtrWidth, TargetInfo}; use roc_target::{PtrWidth, Target};
use roc_types::num::NumericRange; use roc_types::num::NumericRange;
use roc_types::subs::{ use roc_types::subs::{
self, Content, FlatType, GetSubsSlice, OptVariable, RecordFields, Subs, TagExt, TupleElems, 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. /// Layout cache to avoid recomputing [Layout] from a [Variable] multiple times.
#[derive(Debug)] #[derive(Debug)]
pub struct LayoutCache<'a> { pub struct LayoutCache<'a> {
pub target_info: TargetInfo, pub target: Target,
cache: std::vec::Vec<CacheLayer<LayoutResult<'a>>>, cache: std::vec::Vec<CacheLayer<LayoutResult<'a>>>,
raw_function_cache: std::vec::Vec<CacheLayer<RawFunctionLayoutResult<'a>>>, raw_function_cache: std::vec::Vec<CacheLayer<RawFunctionLayoutResult<'a>>>,
@ -128,13 +128,13 @@ pub struct LayoutCache<'a> {
} }
impl<'a> 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); let mut cache = std::vec::Vec::with_capacity(4);
cache.push(Default::default()); cache.push(Default::default());
let mut raw_cache = std::vec::Vec::with_capacity(4); let mut raw_cache = std::vec::Vec::with_capacity(4);
raw_cache.push(Default::default()); raw_cache.push(Default::default());
Self { Self {
target_info, target,
cache, cache,
raw_function_cache: raw_cache, raw_function_cache: raw_cache,
@ -964,39 +964,39 @@ impl<'a> UnionLayout<'a> {
self.discriminant().layout() self.discriminant().layout()
} }
fn stores_tag_id_in_pointer_bits(tags: &[&[InLayout<'a>]], target_info: TargetInfo) -> bool { fn stores_tag_id_in_pointer_bits(tags: &[&[InLayout<'a>]], target: Target) -> bool {
tags.len() < target_info.ptr_width() as usize tags.len() < target.ptr_width() as usize
} }
pub const POINTER_MASK_32BIT: usize = 0b0000_0111; pub const POINTER_MASK_32BIT: usize = 0b0000_0111;
pub const POINTER_MASK_64BIT: usize = 0b0000_0011; pub const POINTER_MASK_64BIT: usize = 0b0000_0011;
pub fn tag_id_pointer_bits_and_mask(target_info: TargetInfo) -> (usize, usize) { pub fn tag_id_pointer_bits_and_mask(target: Target) -> (usize, usize) {
match target_info.ptr_width() { match target.ptr_width() {
PtrWidth::Bytes8 => (3, Self::POINTER_MASK_64BIT), PtrWidth::Bytes8 => (3, Self::POINTER_MASK_64BIT),
PtrWidth::Bytes4 => (2, Self::POINTER_MASK_32BIT), PtrWidth::Bytes4 => (2, Self::POINTER_MASK_32BIT),
} }
} }
// i.e. it is not implicit and not stored in the pointer bits // 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 { match self {
UnionLayout::NonRecursive(_) => true, UnionLayout::NonRecursive(_) => true,
UnionLayout::Recursive(tags) UnionLayout::Recursive(tags)
| UnionLayout::NullableWrapped { | UnionLayout::NullableWrapped {
other_tags: tags, .. 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, 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 { match self {
UnionLayout::NonRecursive(_) => false, UnionLayout::NonRecursive(_) => false,
UnionLayout::Recursive(tags) UnionLayout::Recursive(tags)
| UnionLayout::NullableWrapped { | UnionLayout::NullableWrapped {
other_tags: tags, .. 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, 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 // 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) /// 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); 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::*; use Discriminant::*;
match self.discriminant() { match self.discriminant() {
U0 => (round_up_to_alignment(data_width, data_align), data_align), U0 => (round_up_to_alignment(data_width, data_align), data_align),
@ -1089,7 +1089,7 @@ impl<'a> UnionLayout<'a> {
where where
I: LayoutInterner<'a>, I: LayoutInterner<'a>,
{ {
if !self.stores_tag_id_as_data(interner.target_info()) { if !self.stores_tag_id_as_data(interner.target()) {
return None; return None;
}; };
@ -1151,7 +1151,7 @@ impl<'a> UnionLayout<'a> {
UnionLayout::Recursive(_) UnionLayout::Recursive(_)
| UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NonNullableUnwrapped(_)
| UnionLayout::NullableWrapped { .. } | 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) => { LayoutRepr::Builtin(builtin) => {
use Builtin::*; use Builtin::*;
match interner.target_info().ptr_width() { match interner.target().ptr_width() {
PtrWidth::Bytes4 => { PtrWidth::Bytes4 => {
// more things fit into a register // more things fit into a register
false false
@ -2700,7 +2700,7 @@ impl<'a> LayoutRepr<'a> {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true, LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true,
LayoutRepr::Struct(_) => { LayoutRepr::Struct(_) => {
// TODO: write tests for this! // 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 LayoutRepr::LambdaSet(lambda_set) => interner
@ -2739,7 +2739,7 @@ impl<'a> LayoutRepr<'a> {
use LayoutRepr::*; use LayoutRepr::*;
match self { match self {
Builtin(builtin) => builtin.stack_size(interner.target_info()), Builtin(builtin) => builtin.stack_size(interner.target()),
Struct(field_layouts) => { Struct(field_layouts) => {
let mut sum = 0; let mut sum = 0;
@ -2754,9 +2754,9 @@ impl<'a> LayoutRepr<'a> {
.get_repr(lambda_set.runtime_representation()) .get_repr(lambda_set.runtime_representation())
.stack_size_without_alignment(interner), .stack_size_without_alignment(interner),
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => { 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(_) Recursive(_)
| NullableWrapped { .. } | NullableWrapped { .. }
| NullableUnwrapped { .. } | NullableUnwrapped { .. }
| NonNullableUnwrapped(_) => interner.target_info().ptr_width() as u32, | NonNullableUnwrapped(_) => interner.target().ptr_width() as u32,
} }
} }
LambdaSet(lambda_set) => interner LambdaSet(lambda_set) => interner
.get_repr(lambda_set.runtime_representation()) .get_repr(lambda_set.runtime_representation())
.alignment_bytes(interner), .alignment_bytes(interner),
Builtin(builtin) => builtin.alignment_bytes(interner.target_info()), Builtin(builtin) => builtin.alignment_bytes(interner.target()),
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) => { 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 where
I: LayoutInterner<'a>, I: LayoutInterner<'a>,
{ {
let ptr_width = interner.target_info().ptr_width() as u32; let ptr_width = interner.target().ptr_width() as u32;
use LayoutRepr::*; use LayoutRepr::*;
match self { match self {
@ -2834,7 +2834,7 @@ impl<'a> LayoutRepr<'a> {
} }
Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner), Ptr(inner) => interner.get_repr(*inner).alignment_bytes(interner),
FunctionPointer(_) => ptr_width, 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<InLayout<'a>>; pub type SeenRecPtrs<'a> = VecSet<InLayout<'a>>;
impl<'a> Layout<'a> { impl<'a> Layout<'a> {
pub fn usize(target_info: TargetInfo) -> InLayout<'a> { pub fn usize(target: Target) -> InLayout<'a> {
match target_info.ptr_width() { match target.ptr_width() {
roc_target::PtrWidth::Bytes4 => Layout::U32, roc_target::PtrWidth::Bytes4 => Layout::U32,
roc_target::PtrWidth::Bytes8 => Layout::U64, roc_target::PtrWidth::Bytes8 => Layout::U64,
} }
} }
pub fn isize(target_info: TargetInfo) -> InLayout<'a> { pub fn isize(target: Target) -> InLayout<'a> {
match target_info.ptr_width() { match target.ptr_width() {
roc_target::PtrWidth::Bytes4 => Layout::I32, roc_target::PtrWidth::Bytes4 => Layout::I32,
roc_target::PtrWidth::Bytes8 => Layout::I64, roc_target::PtrWidth::Bytes8 => Layout::I64,
} }
@ -3067,10 +3067,10 @@ impl<'a> Builtin<'a> {
pub const WRAPPER_LEN: u32 = 1; pub const WRAPPER_LEN: u32 = 1;
pub const WRAPPER_CAPACITY: u32 = 2; 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::*; use Builtin::*;
let ptr_width = target_info.ptr_width() as u32; let ptr_width = target.ptr_width() as u32;
match self { match self {
Int(int) => int.stack_size(), 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 std::mem::align_of;
use Builtin::*; 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 // 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 // since both of those are one pointer size, the alignment of that structure is a pointer
// size // size
match self { match self {
Int(int_width) => int_width.alignment_bytes(target_info), Int(int_width) => int_width.alignment_bytes(target),
Float(float_width) => float_width.alignment_bytes(target_info), Float(float_width) => float_width.alignment_bytes(target),
Bool => align_of::<bool>() as u32, Bool => align_of::<bool>() as u32,
Decimal => IntWidth::I128.alignment_bytes(target_info), Decimal => IntWidth::I128.alignment_bytes(target),
// we often treat these as i128 (64-bit systems) // we often treat these as i128 (64-bit systems)
// or i64 (32-bit systems). // or i64 (32-bit systems).
// //
@ -3186,8 +3186,8 @@ impl<'a> Builtin<'a> {
where where
I: LayoutInterner<'a>, I: LayoutInterner<'a>,
{ {
let target_info = interner.target_info(); let target = interner.target();
let ptr_width = target_info.ptr_width() as u32; let ptr_width = target.ptr_width() as u32;
let allocation = match self { let allocation = match self {
Builtin::Str => ptr_width, Builtin::Str => ptr_width,
@ -3196,10 +3196,10 @@ impl<'a> Builtin<'a> {
e.alignment_bytes(interner).max(ptr_width) e.alignment_bytes(interner).max(ptr_width)
} }
// The following are usually not heap-allocated, but they might be when inside a Box. // 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::Int(int_width) => int_width.alignment_bytes(target).max(ptr_width),
Builtin::Float(float_width) => float_width.alignment_bytes(target_info).max(ptr_width), Builtin::Float(float_width) => float_width.alignment_bytes(target).max(ptr_width),
Builtin::Bool => (core::mem::align_of::<bool>() as u32).max(ptr_width), Builtin::Bool => (core::mem::align_of::<bool>() 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) allocation.max(ptr_width)
@ -4788,7 +4788,7 @@ mod test {
#[test] #[test]
fn width_and_alignment_union_empty_struct() { 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 { let lambda_set = LambdaSet {
args: &(&[] as &[InLayout]), args: &(&[] as &[InLayout]),
@ -4813,7 +4813,7 @@ mod test {
#[test] #[test]
fn memcpy_size_result_u32_unit() { 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 { let ok_tag = &[interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)).direct(), repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)).direct(),
@ -4829,13 +4829,13 @@ mod test {
#[test] #[test]
fn void_stack_size() { 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); assert_eq!(Layout::VOID_NAKED.repr(&interner).stack_size(&interner), 0);
} }
#[test] #[test]
fn align_u128_in_tag_union() { 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); assert_eq!(interner.alignment_bytes(Layout::U128), 16);
} }
} }

View file

@ -1,4 +1,4 @@
use roc_target::TargetInfo; use roc_target::Target;
use super::{InLayout, LayoutRepr, UnionLayout}; use super::{InLayout, LayoutRepr, UnionLayout};
@ -27,16 +27,16 @@ impl Erased {
false false
} }
pub fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 { pub fn stack_size_without_alignment(&self, target: Target) -> u32 {
(target_info.ptr_width() as u32) * 3 (target.ptr_width() as u32) * 3
} }
pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 { pub fn alignment_bytes(&self, target: Target) -> u32 {
target_info.ptr_width() as u32 target.ptr_width() as u32
} }
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 { pub fn allocation_alignment_bytes(&self, target: Target) -> u32 {
target_info.ptr_width() as u32 target.ptr_width() as u32
} }
pub fn is_refcounted(&self) -> bool { pub fn is_refcounted(&self) -> bool {

View file

@ -10,7 +10,7 @@ use parking_lot::{Mutex, RwLock};
use roc_builtins::bitcode::{FloatWidth, IntWidth}; use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_collections::{default_hasher, BumpMap}; use roc_collections::{default_hasher, BumpMap};
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_target::TargetInfo; use roc_target::Target;
use crate::layout::LayoutRepr; use crate::layout::LayoutRepr;
@ -208,7 +208,7 @@ pub trait LayoutInterner<'a>: Sized {
self.get_repr(a) == self.get_repr(b) 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 { fn alignment_bytes(&self, layout: InLayout<'a>) -> u32 {
self.get_repr(layout).alignment_bytes(self) self.get_repr(layout).alignment_bytes(self)
@ -545,7 +545,7 @@ struct GlobalLayoutInternerInner<'a> {
map: Mutex<BumpMap<Layout<'a>, InLayout<'a>>>, map: Mutex<BumpMap<Layout<'a>, InLayout<'a>>>,
normalized_lambda_set_map: Mutex<BumpMap<LambdaSet<'a>, LambdaSet<'a>>>, normalized_lambda_set_map: Mutex<BumpMap<LambdaSet<'a>, LambdaSet<'a>>>,
vec: RwLock<Vec<Layout<'a>>>, vec: RwLock<Vec<Layout<'a>>>,
target_info: TargetInfo, target: Target,
} }
/// A derivative of a [GlobalLayoutInterner] interner that provides caching desirable for /// 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>, LambdaSet<'a>>, normalized_lambda_set_map: BumpMap<LambdaSet<'a>, LambdaSet<'a>>,
/// Cache of interned values from the parent for local access. /// Cache of interned values from the parent for local access.
vec: RefCell<Vec<Option<Layout<'a>>>>, vec: RefCell<Vec<Option<Layout<'a>>>>,
target_info: TargetInfo, target: Target,
} }
/// A single-threaded interner, with no concurrency properties. /// A single-threaded interner, with no concurrency properties.
@ -576,7 +576,7 @@ pub struct STLayoutInterner<'a> {
map: BumpMap<Layout<'a>, InLayout<'a>>, map: BumpMap<Layout<'a>, InLayout<'a>>,
normalized_lambda_set_map: BumpMap<LambdaSet<'a>, LambdaSet<'a>>, normalized_lambda_set_map: BumpMap<LambdaSet<'a>, LambdaSet<'a>>,
vec: Vec<Layout<'a>>, vec: Vec<Layout<'a>>,
target_info: TargetInfo, target: Target,
} }
/// Interner constructed with an exclusive lock over [GlobalLayoutInterner] /// Interner constructed with an exclusive lock over [GlobalLayoutInterner]
@ -584,7 +584,7 @@ struct LockedGlobalInterner<'a, 'r> {
map: &'r mut BumpMap<Layout<'a>, InLayout<'a>>, map: &'r mut BumpMap<Layout<'a>, InLayout<'a>>,
normalized_lambda_set_map: &'r mut BumpMap<LambdaSet<'a>, LambdaSet<'a>>, normalized_lambda_set_map: &'r mut BumpMap<LambdaSet<'a>, LambdaSet<'a>>,
vec: &'r mut Vec<Layout<'a>>, vec: &'r mut Vec<Layout<'a>>,
target_info: TargetInfo, target: Target,
} }
/// Generic hasher for a value, to be used by all interners. /// 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> { impl<'a> GlobalLayoutInterner<'a> {
/// Creates a new global interner with the given capacity. /// Creates a new global interner with the given capacity.
pub fn with_capacity(cap: usize, target_info: TargetInfo) -> Self { pub fn with_capacity(cap: usize, target: Target) -> Self {
STLayoutInterner::with_capacity(cap, target_info).into_global() STLayoutInterner::with_capacity(cap, target).into_global()
} }
/// Creates a derivative [TLLayoutInterner] pointing back to this global interner. /// Creates a derivative [TLLayoutInterner] pointing back to this global interner.
@ -625,7 +625,7 @@ impl<'a> GlobalLayoutInterner<'a> {
map: Default::default(), map: Default::default(),
normalized_lambda_set_map: Default::default(), normalized_lambda_set_map: Default::default(),
vec: Default::default(), vec: Default::default(),
target_info: self.0.target_info, target: self.0.target,
} }
} }
@ -637,7 +637,7 @@ impl<'a> GlobalLayoutInterner<'a> {
map, map,
normalized_lambda_set_map, normalized_lambda_set_map,
vec, vec,
target_info, target,
} = match Arc::try_unwrap(self.0) { } = match Arc::try_unwrap(self.0) {
Ok(inner) => inner, Ok(inner) => inner,
Err(li) => return Err(Self(li)), Err(li) => return Err(Self(li)),
@ -649,7 +649,7 @@ impl<'a> GlobalLayoutInterner<'a> {
map, map,
normalized_lambda_set_map, normalized_lambda_set_map,
vec, vec,
target_info, target,
}) })
} }
@ -703,7 +703,7 @@ impl<'a> GlobalLayoutInterner<'a> {
map: &mut map, map: &mut map,
normalized_lambda_set_map: &mut normalized_lambda_set_map, normalized_lambda_set_map: &mut normalized_lambda_set_map,
vec: &mut vec, vec: &mut vec,
target_info: self.0.target_info, target: self.0.target,
}; };
reify::reify_lambda_set_captures(arena, &mut interner, slot, normalized.set) reify::reify_lambda_set_captures(arena, &mut interner, slot, normalized.set)
} else { } else {
@ -765,7 +765,7 @@ impl<'a> GlobalLayoutInterner<'a> {
map: &mut map, map: &mut map,
normalized_lambda_set_map: &mut normalized_lambda_set_map, normalized_lambda_set_map: &mut normalized_lambda_set_map,
vec: &mut vec, 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); let full_layout = reify::reify_recursive_layout(arena, &mut interner, slot, normalized);
@ -927,19 +927,19 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {
value value
} }
fn target_info(&self) -> TargetInfo { fn target(&self) -> Target {
self.target_info self.target
} }
} }
impl<'a> STLayoutInterner<'a> { impl<'a> STLayoutInterner<'a> {
/// Creates a new single threaded interner with the given capacity. /// 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 { let mut interner = Self {
map: BumpMap::with_capacity_and_hasher(cap, default_hasher()), map: BumpMap::with_capacity_and_hasher(cap, default_hasher()),
normalized_lambda_set_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), vec: Vec::with_capacity(cap),
target_info, target,
}; };
fill_reserved_layouts(&mut interner); fill_reserved_layouts(&mut interner);
interner interner
@ -954,13 +954,13 @@ impl<'a> STLayoutInterner<'a> {
map, map,
normalized_lambda_set_map, normalized_lambda_set_map,
vec, vec,
target_info, target,
} = self; } = self;
GlobalLayoutInterner(Arc::new(GlobalLayoutInternerInner { GlobalLayoutInterner(Arc::new(GlobalLayoutInternerInner {
map: Mutex::new(map), map: Mutex::new(map),
normalized_lambda_set_map: Mutex::new(normalized_lambda_set_map), normalized_lambda_set_map: Mutex::new(normalized_lambda_set_map),
vec: RwLock::new(vec), vec: RwLock::new(vec),
target_info, target,
})) }))
} }
@ -1072,8 +1072,8 @@ macro_rules! st_impl {
self.vec[index] self.vec[index]
} }
fn target_info(&self) -> TargetInfo { fn target(&self) -> Target{
self.target_info self.target
} }
} }
}; };
@ -1758,13 +1758,13 @@ pub mod dbg_stable {
mod insert_lambda_set { mod insert_lambda_set {
use bumpalo::Bump; use bumpalo::Bump;
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_target::TargetInfo; use roc_target::Target;
use crate::layout::{LambdaSet, Layout, LayoutRepr, SemanticRepr}; use crate::layout::{LambdaSet, Layout, LayoutRepr, SemanticRepr};
use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup}; use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup};
const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64(); const TARGET: Target = Target::LinuxX64;
const TEST_SET: &&[(Symbol, &[InLayout])] = const TEST_SET: &&[(Symbol, &[InLayout])] =
&(&[(Symbol::ATTR_ATTR, &[Layout::UNIT] as &[_])] as &[_]); &(&[(Symbol::ATTR_ATTR, &[Layout::UNIT] as &[_])] as &[_]);
const TEST_ARGS: &&[InLayout] = &(&[Layout::UNIT] as &[_]); const TEST_ARGS: &&[InLayout] = &(&[Layout::UNIT] as &[_]);
@ -1776,7 +1776,7 @@ mod insert_lambda_set {
fn two_threads_write() { fn two_threads_write() {
for _ in 0..100 { for _ in 0..100 {
let mut arenas: Vec<_> = std::iter::repeat_with(Bump::new).take(10).collect(); 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 set = TEST_SET;
let repr = Layout::UNIT; let repr = Layout::UNIT;
std::thread::scope(|s| { std::thread::scope(|s| {
@ -1797,7 +1797,7 @@ mod insert_lambda_set {
#[test] #[test]
fn insert_then_reintern() { fn insert_then_reintern() {
let arena = &Bump::new(); 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 mut interner = global.fork();
let lambda_set = let lambda_set =
@ -1812,7 +1812,7 @@ mod insert_lambda_set {
#[test] #[test]
fn write_global_then_single_threaded() { fn write_global_then_single_threaded() {
let arena = &Bump::new(); let arena = &Bump::new();
let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); let global = GlobalLayoutInterner::with_capacity(2, TARGET);
let set = TEST_SET; let set = TEST_SET;
let repr = Layout::UNIT; let repr = Layout::UNIT;
@ -1832,7 +1832,7 @@ mod insert_lambda_set {
#[test] #[test]
fn write_single_threaded_then_global() { fn write_single_threaded_then_global() {
let arena = &Bump::new(); 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 mut st_interner = global.unwrap().unwrap();
let set = TEST_SET; let set = TEST_SET;
@ -1852,13 +1852,13 @@ mod insert_lambda_set {
#[cfg(test)] #[cfg(test)]
mod insert_recursive_layout { mod insert_recursive_layout {
use bumpalo::Bump; use bumpalo::Bump;
use roc_target::TargetInfo; use roc_target::Target;
use crate::layout::{Builtin, InLayout, Layout, LayoutRepr, SemanticRepr, UnionLayout}; use crate::layout::{Builtin, InLayout, Layout, LayoutRepr, SemanticRepr, UnionLayout};
use super::{GlobalLayoutInterner, LayoutInterner}; 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> { fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> {
let list_rec = Layout { let list_rec = Layout {
@ -1905,7 +1905,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn write_two_threads() { fn write_two_threads() {
let arena = &Bump::new(); let arena = &Bump::new();
let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); let global = GlobalLayoutInterner::with_capacity(2, TARGET);
let layout = { let layout = {
let mut interner = global.fork(); let mut interner = global.fork();
make_layout(arena, &mut interner) make_layout(arena, &mut interner)
@ -1927,7 +1927,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn write_twice_thread_local_single_thread() { fn write_twice_thread_local_single_thread() {
let arena = &Bump::new(); 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 mut interner = global.fork();
let layout = make_layout(arena, &mut interner); let layout = make_layout(arena, &mut interner);
@ -1943,7 +1943,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn write_twice_single_thread() { fn write_twice_single_thread() {
let arena = &Bump::new(); 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 mut interner = GlobalLayoutInterner::unwrap(global).unwrap();
let layout = make_layout(arena, &mut interner); let layout = make_layout(arena, &mut interner);
@ -1960,7 +1960,7 @@ mod insert_recursive_layout {
fn many_threads_read_write() { fn many_threads_read_write() {
for _ in 0..100 { for _ in 0..100 {
let mut arenas: Vec<_> = std::iter::repeat_with(Bump::new).take(10).collect(); 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| { std::thread::scope(|s| {
let mut handles = Vec::with_capacity(10); let mut handles = Vec::with_capacity(10);
for arena in arenas.iter_mut() { for arena in arenas.iter_mut() {
@ -1983,7 +1983,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn insert_then_reintern() { fn insert_then_reintern() {
let arena = &Bump::new(); 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 mut interner = global.fork();
let layout = make_layout(arena, &mut interner); let layout = make_layout(arena, &mut interner);
@ -1996,7 +1996,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn write_global_then_single_threaded() { fn write_global_then_single_threaded() {
let arena = &Bump::new(); let arena = &Bump::new();
let global = GlobalLayoutInterner::with_capacity(2, TARGET_INFO); let global = GlobalLayoutInterner::with_capacity(2, TARGET);
let layout = { let layout = {
let mut interner = global.fork(); let mut interner = global.fork();
make_layout(arena, &mut interner) make_layout(arena, &mut interner)
@ -2018,7 +2018,7 @@ mod insert_recursive_layout {
#[test] #[test]
fn write_single_threaded_then_global() { fn write_single_threaded_then_global() {
let arena = &Bump::new(); 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 mut st_interner = global.unwrap().unwrap();
let layout = make_layout(arena, &mut st_interner); let layout = make_layout(arena, &mut st_interner);

View file

@ -20,7 +20,7 @@ use bumpalo::collections::CollectIn;
use roc_collections::{MutMap, MutSet}; use roc_collections::{MutMap, MutSet};
use roc_module::low_level::LowLevel; use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_target::TargetInfo; use roc_target::Target;
/** /**
Insert reset and reuse operations into the IR. Insert reset and reuse operations into the IR.
@ -30,7 +30,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>(
arena: &'a Bump, arena: &'a Bump,
layout_interner: &'i STLayoutInterner<'a>, layout_interner: &'i STLayoutInterner<'a>,
home: ModuleId, home: ModuleId,
target_info: TargetInfo, target: Target,
ident_ids: &'i mut IdentIds, ident_ids: &'i mut IdentIds,
update_mode_ids: &'i mut UpdateModeIds, update_mode_ids: &'i mut UpdateModeIds,
procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>, 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( let new_proc = insert_reset_reuse_operations_proc(
arena, arena,
layout_interner, layout_interner,
target_info, target,
home, home,
ident_ids, ident_ids,
update_mode_ids, update_mode_ids,
@ -58,7 +58,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>(
fn insert_reset_reuse_operations_proc<'a, 'i>( fn insert_reset_reuse_operations_proc<'a, 'i>(
arena: &'a Bump, arena: &'a Bump,
layout_interner: &'i STLayoutInterner<'a>, layout_interner: &'i STLayoutInterner<'a>,
target_info: TargetInfo, target: Target,
home: ModuleId, home: ModuleId,
ident_ids: &'i mut IdentIds, ident_ids: &'i mut IdentIds,
update_mode_ids: &'i mut UpdateModeIds, update_mode_ids: &'i mut UpdateModeIds,
@ -70,7 +70,7 @@ fn insert_reset_reuse_operations_proc<'a, 'i>(
} }
let mut env = ReuseEnvironment { let mut env = ReuseEnvironment {
target_info, target,
symbol_tags: MutMap::default(), symbol_tags: MutMap::default(),
non_unique_symbols: MutSet::default(), non_unique_symbols: MutSet::default(),
reuse_tokens: MutMap::default(), reuse_tokens: MutMap::default(),
@ -464,7 +464,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
), ),
ModifyRc::Free(_) => { ModifyRc::Free(_) => {
if union_layout 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()), 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. // 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 { let mut first_pass_body_environment = ReuseEnvironment {
target_info: environment.target_info, target: environment.target,
symbol_tags: environment.symbol_tags.clone(), symbol_tags: environment.symbol_tags.clone(),
non_unique_symbols: environment.non_unique_symbols.clone(), non_unique_symbols: environment.non_unique_symbols.clone(),
reuse_tokens: max_reuse_token_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) = { 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. // 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 { let mut body_environment = ReuseEnvironment {
target_info: environment.target_info, target: environment.target,
symbol_tags: environment.symbol_tags.clone(), symbol_tags: environment.symbol_tags.clone(),
non_unique_symbols: environment.non_unique_symbols.clone(), non_unique_symbols: environment.non_unique_symbols.clone(),
reuse_tokens: used_reuse_tokens.clone(), reuse_tokens: used_reuse_tokens.clone(),
@ -1182,7 +1182,7 @@ enum JoinPointReuseTokens<'a> {
#[derive(Clone)] #[derive(Clone)]
struct ReuseEnvironment<'a> { struct ReuseEnvironment<'a> {
target_info: TargetInfo, target: Target,
symbol_tags: MutMap<Symbol, Tag>, symbol_tags: MutMap<Symbol, Tag>,
non_unique_symbols: MutSet<Symbol>, non_unique_symbols: MutSet<Symbol>,
reuse_tokens: ReuseTokens<'a>, reuse_tokens: ReuseTokens<'a>,

View file

@ -8,6 +8,8 @@ license.workspace = true
version.workspace = true version.workspace = true
[dependencies] [dependencies]
roc_error_macros = { path = "../../error_macros" }
strum.workspace = true strum.workspace = true
strum_macros.workspace = true strum_macros.workspace = true
target-lexicon.workspace = true target-lexicon.workspace = true

View file

@ -3,70 +3,104 @@
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check. // See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)] #![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; use target_lexicon::Triple;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum OperatingSystem { pub enum OperatingSystem {
Freestanding,
Linux,
Mac,
Windows, Windows,
Unix,
Wasi,
} }
impl OperatingSystem { #[repr(u8)]
pub const fn new(target: target_lexicon::OperatingSystem) -> Option<Self> { #[derive(Debug, Clone, Copy, PartialEq, Eq)]
match target { pub enum PtrWidth {
target_lexicon::OperatingSystem::Windows => Some(OperatingSystem::Windows), Bytes4 = 4,
target_lexicon::OperatingSystem::Wasi => Some(OperatingSystem::Wasi), Bytes8 = 8,
target_lexicon::OperatingSystem::Linux => Some(OperatingSystem::Unix), }
target_lexicon::OperatingSystem::MacOSX { .. } => Some(OperatingSystem::Unix),
target_lexicon::OperatingSystem::Darwin => Some(OperatingSystem::Unix), #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter, EnumCount)]
target_lexicon::OperatingSystem::Unknown => Some(OperatingSystem::Unix), pub enum Architecture {
_ => None, Aarch32,
Aarch64,
Wasm32,
X86_32,
X86_64,
}
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)
} }
} }
pub const fn object_file_ext(&self) -> &str { impl Architecture {
match self {
OperatingSystem::Windows => "obj",
OperatingSystem::Unix => "o",
OperatingSystem::Wasi => "wasm",
}
}
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 From<target_lexicon::OperatingSystem> 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 {
pub const fn ptr_width(&self) -> PtrWidth { 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 { pub const fn ptr_size(&self) -> usize {
@ -85,196 +119,177 @@ impl TargetInfo {
} }
pub const fn ptr_alignment_bytes(&self) -> usize { pub const fn ptr_alignment_bytes(&self) -> usize {
self.architecture.ptr_alignment_bytes() self.architecture().ptr_alignment_bytes()
} }
pub const fn default_aarch64() -> Self { pub const fn object_file_ext(&self) -> &str {
TargetInfo { use Target::*;
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::*;
match self { match self {
X86_64 | Aarch64 => PtrWidth::Bytes8, LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "o",
X86_32 | Aarch32 | Wasm32 => PtrWidth::Bytes4, WinX32 | WinX64 | WinArm64 => "obj",
Wasm32 => "wasm",
} }
} }
pub const fn ptr_alignment_bytes(&self) -> usize { pub const fn static_library_file_ext(&self) -> &str {
self.ptr_width() as usize use Target::*;
}
}
impl From<target_lexicon::Architecture> 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::*;
match self { match self {
Target::System => Triple::host(), LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "a",
Target::LinuxX32 => Triple { WinX32 | WinX64 | WinArm64 => "lib",
architecture: Architecture::X86_32(X86_32Architecture::I386), Wasm32 => "wasm",
vendor: Vendor::Unknown, }
operating_system: OperatingSystem::Linux, }
environment: Environment::Unknown,
binary_format: BinaryFormat::Elf, pub const fn executable_file_ext(&self) -> Option<&str> {
}, use Target::*;
Target::LinuxX64 => Triple { match self {
architecture: Architecture::X86_64, LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => None,
vendor: Vendor::Unknown, WinX32 | WinX64 | WinArm64 => Some("exe"),
operating_system: OperatingSystem::Linux, Wasm32 => Some("wasm"),
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,
},
} }
} }
} }
impl From<&Target> for Triple { pub enum ParseError {
InvalidTargetString,
}
impl FromStr for Target {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
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<Target> for &'static str {
fn from(target: Target) -> Self {
Self::from(&target)
}
}
impl From<&Target> for &'static str {
fn from(target: &Target) -> Self { 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<Triple> 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<Self, Self::Error> {
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)) 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,
}
}

View file

@ -517,7 +517,7 @@ where
{ {
let arena = Bump::new(); let arena = Bump::new();
let (builtin_module, source, path) = module_source_and_path(builtin); 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 { let LoadedModule {
mut interns, mut interns,
@ -531,7 +531,7 @@ where
source, source,
path.parent().unwrap().to_path_buf(), path.parent().unwrap().to_path_buf(),
Default::default(), Default::default(),
target_info, target,
FunctionKind::LambdaSet, FunctionKind::LambdaSet,
roc_reporting::report::RenderTarget::ColorTerminal, roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE, roc_reporting::report::DEFAULT_PALETTE,

View file

@ -22,8 +22,8 @@ fn width_and_alignment_u8_u8() {
use roc_mono::layout::Layout; use roc_mono::layout::Layout;
use roc_mono::layout::UnionLayout; use roc_mono::layout::UnionLayout;
let target_info = roc_target::TargetInfo::default_x86_64(); let target = roc_target::Target::LinuxX64;
let interner = STLayoutInterner::with_capacity(4, target_info); let interner = STLayoutInterner::with_capacity(4, target);
let t = &[Layout::U8] as &[_]; let t = &[Layout::U8] as &[_];
let tt = [t, t]; let tt = [t, t];

View file

@ -56,7 +56,7 @@ pub fn helper(
} }
let load_config = LoadConfig { let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(), target: roc_target::Target::LinuxX64,
render: roc_reporting::report::RenderTarget::ColorTerminal, render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE, palette: roc_reporting::report::DEFAULT_PALETTE,
threading: Threading::Single, threading: Threading::Single,
@ -197,14 +197,9 @@ pub fn helper(
mode: roc_gen_dev::AssemblyBackendMode::Test, mode: roc_gen_dev::AssemblyBackendMode::Test,
}; };
let target = target_lexicon::Triple::host(); let target = target_lexicon::Triple::host().into();
let module_object = roc_gen_dev::build_module( let module_object =
&env, roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures);
&mut interns,
&mut layout_interner,
&target,
procedures,
);
let module_out = module_object let module_out = module_object
.write() .write()
@ -215,7 +210,7 @@ pub fn helper(
roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
let (mut child, dylib_path) = link( let (mut child, dylib_path) = link(
&target, target,
app_o_file.clone(), app_o_file.clone(),
// Long term we probably want a smarter way to link in zig builtins. // 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. // With the current method all methods are kept and it adds about 100k to all outputs.

View file

@ -16,7 +16,7 @@ use roc_mono::ir::{CrashTag, OptLevel, SingleEntryPoint};
use roc_packaging::cache::RocCacheDir; use roc_packaging::cache::RocCacheDir;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use target_lexicon::Triple; use roc_target::Target;
#[cfg(feature = "gen-llvm-wasm")] #[cfg(feature = "gen-llvm-wasm")]
use crate::helpers::from_wasm32_memory::FromWasm32Memory; use crate::helpers::from_wasm32_memory::FromWasm32Memory;
@ -52,11 +52,9 @@ fn create_llvm_module<'a>(
src: &str, src: &str,
config: HelperConfig, config: HelperConfig,
context: &'a inkwell::context::Context, context: &'a inkwell::context::Context,
target: &Triple, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
) -> (&'static str, String, &'a Module<'a>) { ) -> (&'static str, String, &'a Module<'a>) {
let target_info = roc_target::TargetInfo::from(target);
let filename = PathBuf::from("Test.roc"); let filename = PathBuf::from("Test.roc");
let src_dir = PathBuf::from("fake/test/path"); let src_dir = PathBuf::from("fake/test/path");
@ -72,7 +70,7 @@ fn create_llvm_module<'a>(
} }
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::ColorTerminal, render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
@ -227,7 +225,7 @@ fn create_llvm_module<'a>(
context, context,
interns, interns,
module, module,
target_info, target,
mode: config.mode, mode: config.mode,
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
@ -332,33 +330,21 @@ pub fn helper<'a>(
context: &'a inkwell::context::Context, context: &'a inkwell::context::Context,
function_kind: FunctionKind, function_kind: FunctionKind,
) -> (&'static str, String, Library) { ) -> (&'static str, String, Library) {
let target = target_lexicon::Triple::host(); let target = target_lexicon::Triple::host().into();
let (main_fn_name, delayed_errors, module) = 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 { if !config.emit_debug_info {
module.strip_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"); let lib = res_lib.expect("Error loading compiled dylib for test");
(main_fn_name, delayed_errors, lib) (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)] #[allow(dead_code)]
fn write_final_wasm() -> bool { fn write_final_wasm() -> bool {
#[allow(unused_imports)] #[allow(unused_imports)]
@ -383,10 +369,10 @@ fn compile_to_wasm_bytes<'a>(
static TEMP_DIR: OnceLock<tempfile::TempDir> = OnceLock::new(); static TEMP_DIR: OnceLock<tempfile::TempDir> = OnceLock::new();
let temp_dir = TEMP_DIR.get_or_init(|| tempfile::tempdir().unwrap()); 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) = 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 content_hash = crate::helpers::src_hash(src);
let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module); let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module);

View file

@ -88,7 +88,7 @@ fn compile_roc_to_wasm_bytes<'a, T: Wasm32Result>(
} }
let load_config = LoadConfig { let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_wasm32(), target: roc_target::Target::Wasm32,
render: roc_reporting::report::RenderTarget::ColorTerminal, render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE_HTML, palette: DEFAULT_PALETTE_HTML,
threading: Threading::Single, threading: Threading::Single,

View file

@ -2,7 +2,7 @@
use bumpalo::Bump; use bumpalo::Bump;
use roc_gen_wasm::Env; use roc_gen_wasm::Env;
use roc_target::TargetInfo; use roc_target::Target;
use std::fs; use std::fs;
use std::process::Command; use std::process::Command;
@ -259,7 +259,7 @@ fn test_help(
dump_filename: &str, dump_filename: &str,
) { ) {
let arena = Bump::new(); 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 { let BackendInputs {
env, env,

View file

@ -27,7 +27,7 @@ use roc_mono::ir::ProcLayout;
use roc_mono::layout::STLayoutInterner; use roc_mono::layout::STLayoutInterner;
use test_mono_macros::*; 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 /// Without this, some tests pass in `cargo test --release` but fail without
/// the --release flag because they run out of stack space. This increases /// 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 { let load_config = LoadConfig {
target_info: TARGET_INFO, target: TARGET,
// TODO parameterize // TODO parameterize
function_kind: FunctionKind::LambdaSet, function_kind: FunctionKind::LambdaSet,
threading: Threading::Single, threading: Threading::Single,

View file

@ -79,7 +79,7 @@ pub fn run_load_and_infer<'a>(
file_path, file_path,
module_src, module_src,
dir.path().to_path_buf(), dir.path().to_path_buf(),
roc_target::TargetInfo::default_x86_64(), roc_target::Target::LinuxX64,
function_kind, function_kind,
roc_reporting::report::RenderTarget::Generic, roc_reporting::report::RenderTarget::Generic,
RocCacheDir::Disallowed, RocCacheDir::Disallowed,

View file

@ -43,7 +43,7 @@ pub(crate) fn write_compiled_ir<'a>(
let file_path = dir.path().join(filename); let file_path = dir.path().join(filename);
let load_config = LoadConfig { let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(), target: roc_target::Target::LinuxX64,
function_kind: compiler_settings.function_kind, function_kind: compiler_settings.function_kind,
threading: Threading::Single, threading: Threading::Single,
render: roc_reporting::report::RenderTarget::Generic, render: roc_reporting::report::RenderTarget::Generic,

View file

@ -462,7 +462,7 @@ fn render_sidebar<'a, I: Iterator<Item = &'a ModuleDocumentation>>(modules: I) -
pub fn load_module_for_docs(filename: PathBuf) -> LoadedModule { pub fn load_module_for_docs(filename: PathBuf) -> LoadedModule {
let arena = Bump::new(); let arena = Bump::new();
let load_config = LoadConfig { 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, function_kind: roc_solve::FunctionKind::LambdaSet,
render: roc_reporting::report::RenderTarget::ColorTerminal, render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE, palette: roc_reporting::report::DEFAULT_PALETTE,

View file

@ -16,7 +16,8 @@ Architecture : [
] ]
OperatingSystem : [ OperatingSystem : [
Freestanding,
Linux,
Mac,
Windows, Windows,
Unix,
Wasi,
] ]

View file

@ -176,16 +176,18 @@ pub struct Target {
#[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)] #[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)]
#[repr(u8)] #[repr(u8)]
pub enum OperatingSystem { pub enum OperatingSystem {
Unix = 0, Freestanding = 0,
Wasi = 1, Linux = 1,
Windows = 2, Mac = 2,
Windows = 3,
} }
impl core::fmt::Debug for OperatingSystem { impl core::fmt::Debug for OperatingSystem {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::Unix => f.write_str("OperatingSystem::Unix"), Self::Freestanding => f.write_str("OperatingSystem::Freestanding"),
Self::Wasi => f.write_str("OperatingSystem::Wasi"), Self::Linux => f.write_str("OperatingSystem::Linux"),
Self::Mac => f.write_str("OperatingSystem::Mac"),
Self::Windows => f.write_str("OperatingSystem::Windows"), Self::Windows => f.write_str("OperatingSystem::Windows"),
} }
} }

View file

@ -17,7 +17,7 @@ use roc_mono::ir::{generate_glue_procs, CrashTag, GlueProc, OptLevel};
use roc_mono::layout::{GlobalLayoutInterner, LayoutCache, LayoutInterner}; use roc_mono::layout::{GlobalLayoutInterner, LayoutCache, LayoutInterner};
use roc_packaging::cache::{self, RocCacheDir}; use roc_packaging::cache::{self, RocCacheDir};
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; 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 roc_types::subs::{Subs, Variable};
use std::fs::File; use std::fs::File;
use std::io::{self, ErrorKind, Write}; use std::io::{self, ErrorKind, Write};
@ -41,16 +41,17 @@ pub fn generate(
spec_path: &Path, spec_path: &Path,
backend: CodeGenBackend, backend: CodeGenBackend,
) -> io::Result<i32> { ) -> io::Result<i32> {
let target = Triple::host().into();
// TODO: Add verification around the paths. Make sure they heav the correct file extension and what not. // TODO: Add verification around the paths. Make sure they heav the correct file extension and what not.
match load_types( match load_types(
input_path.to_path_buf(), input_path.to_path_buf(),
Threading::AllAvailable, Threading::AllAvailable,
IgnoreErrors::NONE, IgnoreErrors::NONE,
target,
) { ) {
Ok(types) => { Ok(types) => {
// TODO: we should to modify the app file first before loading it. // 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. // 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 { let code_gen_options = CodeGenOptions {
backend, backend,
@ -61,14 +62,14 @@ pub fn generate(
}; };
let load_config = standard_load_config( let load_config = standard_load_config(
&triple, target,
BuildOrdering::BuildIfChecks, BuildOrdering::BuildIfChecks,
Threading::AllAvailable, Threading::AllAvailable,
); );
let arena = ManuallyDrop::new(Bump::new()); let arena = ManuallyDrop::new(Bump::new());
let link_type = LinkType::Dylib; 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 LinkingStrategy::Surgical
} else { } else {
LinkingStrategy::Legacy LinkingStrategy::Legacy
@ -79,7 +80,7 @@ pub fn generate(
let res_binary_path = match tempdir_res { let res_binary_path = match tempdir_res {
Ok(dylib_dir) => build_file( Ok(dylib_dir) => build_file(
&arena, &arena,
&triple, target,
spec_path.to_path_buf(), spec_path.to_path_buf(),
code_gen_options, code_gen_options,
false, false,
@ -105,12 +106,10 @@ pub fn generate(
expect_metadata: _, expect_metadata: _,
}) => { }) => {
// TODO: Should binary_path be update to deal with extensions? // TODO: Should binary_path be update to deal with extensions?
use target_lexicon::OperatingSystem; use roc_target::OperatingSystem;
let lib_path = match triple.operating_system { let lib_path = match target.operating_system() {
OperatingSystem::Windows => binary_path.with_extension("dll"), OperatingSystem::Windows => binary_path.with_extension("dll"),
OperatingSystem::Darwin | OperatingSystem::MacOSX { .. } => { OperatingSystem::Mac => binary_path.with_extension("dylib"),
binary_path.with_extension("dylib")
}
_ => binary_path.with_extension("so.1.0"), _ => binary_path.with_extension("so.1.0"),
}; };
@ -398,8 +397,8 @@ pub fn load_types(
full_file_path: PathBuf, full_file_path: PathBuf,
threading: Threading, threading: Threading,
ignore_errors: IgnoreErrors, ignore_errors: IgnoreErrors,
target: Target,
) -> Result<Vec<Types>, io::Error> { ) -> Result<Vec<Types>, io::Error> {
let target_info = (&Triple::host()).into();
// TODO the function kind may need to be parameterizable. // TODO the function kind may need to be parameterizable.
let function_kind = FunctionKind::LambdaSet; let function_kind = FunctionKind::LambdaSet;
let arena = &Bump::new(); let arena = &Bump::new();
@ -417,7 +416,7 @@ pub fn load_types(
full_file_path, full_file_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LoadConfig { LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::Generic, render: RenderTarget::Generic,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
@ -456,18 +455,19 @@ pub fn load_types(
exposed_to_host.get(&symbol).copied() exposed_to_host.get(&symbol).copied()
}); });
let operating_system = target_info.operating_system; let operating_system = target.operating_system();
let architectures = Architecture::iter(); let architectures = Architecture::iter();
let mut arch_types = Vec::with_capacity(architectures.len()); let mut arch_types = Vec::with_capacity(architectures.len());
for architecture in architectures { for architecture in architectures {
let mut interns = interns.clone(); // TODO there may be a way to avoid this. let mut interns = interns.clone(); // TODO there may be a way to avoid this.
let target_info = TargetInfo { let target = match Target::try_from((architecture, operating_system)) {
architecture, Ok(t) => t,
operating_system, 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 glue_procs_by_layout = MutMap::default();
let mut extern_names = MutMap::default(); let mut extern_names = MutMap::default();
@ -528,7 +528,7 @@ pub fn load_types(
arena.alloc(interns), arena.alloc(interns),
glue_procs_by_layout, glue_procs_by_layout,
layout_cache, layout_cache,
target_info, target,
exposed_to_host.clone(), exposed_to_host.clone(),
); );

View file

@ -195,16 +195,18 @@ pub struct Target {
#[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)] #[derive(Clone, Copy, Eq, Ord, Hash, PartialEq, PartialOrd)]
#[repr(u8)] #[repr(u8)]
pub enum OperatingSystem { pub enum OperatingSystem {
Unix = 0, Freestanding = 0,
Wasi = 1, Linux = 1,
Windows = 2, Mac = 2,
Windows = 3,
} }
impl core::fmt::Debug for OperatingSystem { impl core::fmt::Debug for OperatingSystem {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self { match self {
Self::Unix => f.write_str("OperatingSystem::Unix"), Self::Freestanding => f.write_str("OperatingSystem::Freestanding"),
Self::Wasi => f.write_str("OperatingSystem::Wasi"), Self::Linux => f.write_str("OperatingSystem::Linux"),
Self::Mac => f.write_str("OperatingSystem::Mac"),
Self::Windows => f.write_str("OperatingSystem::Windows"), Self::Windows => f.write_str("OperatingSystem::Windows"),
} }
} }

View file

@ -20,7 +20,7 @@ use roc_mono::{
InLayout, Layout, LayoutCache, LayoutInterner, LayoutRepr, TLLayoutInterner, UnionLayout, InLayout, Layout, LayoutCache, LayoutInterner, LayoutRepr, TLLayoutInterner, UnionLayout,
}, },
}; };
use roc_target::{Architecture, OperatingSystem, TargetInfo}; use roc_target::{Architecture, OperatingSystem, Target};
use roc_types::{ use roc_types::{
subs::{Content, FlatType, GetSubsSlice, Label, Subs, SubsSlice, UnionLabels, Variable}, subs::{Content, FlatType, GetSubsSlice, Label, Subs, SubsSlice, UnionLabels, Variable},
types::{AliasKind, RecordField}, types::{AliasKind, RecordField},
@ -65,13 +65,13 @@ pub struct Types {
/// This is important for declaration order in C; we need to output a /// 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. /// type declaration earlier in the file than where it gets referenced by another type.
deps: VecMap<TypeId, Vec<TypeId>>, deps: VecMap<TypeId, Vec<TypeId>>,
target: TargetInfo, target: Target,
} }
impl Types { impl Types {
const UNIT: TypeId = TypeId(0); 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 types = Vec::with_capacity(cap);
let mut sizes = Vec::with_capacity(cap); let mut sizes = Vec::with_capacity(cap);
let mut aligns = Vec::with_capacity(cap); let mut aligns = Vec::with_capacity(cap);
@ -81,7 +81,7 @@ impl Types {
aligns.push(1); aligns.push(1);
Self { Self {
target: target_info, target,
types, types,
sizes, sizes,
aligns, aligns,
@ -98,7 +98,7 @@ impl Types {
interns: &'a Interns, interns: &'a Interns,
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>, glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
layout_cache: LayoutCache<'a>, layout_cache: LayoutCache<'a>,
target: TargetInfo, target: Target,
mut entry_points: MutMap<Symbol, Variable>, mut entry_points: MutMap<Symbol, Variable>,
) -> Self { ) -> Self {
let mut types = Self::with_capacity(entry_points.len(), target); 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 self.target
} }
} }
@ -905,11 +905,11 @@ impl From<&Option<TypeId>> for roc_type::U1 {
} }
} }
impl From<TargetInfo> for roc_type::Target { impl From<Target> for roc_type::Target {
fn from(target: TargetInfo) -> Self { fn from(target: Target) -> Self {
roc_type::Target { roc_type::Target {
architecture: target.architecture.into(), architecture: target.architecture().into(),
operatingSystem: target.operating_system.into(), operatingSystem: target.operating_system().into(),
} }
} }
} }
@ -928,10 +928,12 @@ impl From<Architecture> for roc_type::Architecture {
impl From<OperatingSystem> for roc_type::OperatingSystem { impl From<OperatingSystem> for roc_type::OperatingSystem {
fn from(os: OperatingSystem) -> Self { fn from(os: OperatingSystem) -> Self {
// TODO: Update Glue to new OS Tags.
match os { match os {
OperatingSystem::Windows => roc_type::OperatingSystem::Windows, OperatingSystem::Windows => roc_type::OperatingSystem::Windows,
OperatingSystem::Unix => roc_type::OperatingSystem::Unix, OperatingSystem::Linux => roc_type::OperatingSystem::Linux,
OperatingSystem::Wasi => roc_type::OperatingSystem::Wasi, OperatingSystem::Mac => roc_type::OperatingSystem::Mac,
OperatingSystem::Freestanding => roc_type::OperatingSystem::Freestanding,
} }
} }
} }
@ -1179,7 +1181,7 @@ impl<'a> Env<'a> {
interns: &'a Interns, interns: &'a Interns,
layout_interner: TLLayoutInterner<'a>, layout_interner: TLLayoutInterner<'a>,
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>, glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
target: TargetInfo, target: Target,
) -> Self { ) -> Self {
Env { Env {
arena, arena,

View file

@ -112,7 +112,7 @@ pub(crate) fn global_analysis(doc_info: DocInfo) -> Vec<AnalyzedDocument> {
fi, fi,
&doc_info.source, &doc_info.source,
src_dir, src_dir,
roc_target::TargetInfo::default_x86_64(), roc_target::Target::LinuxX64,
roc_load::FunctionKind::LambdaSet, roc_load::FunctionKind::LambdaSet,
roc_reporting::report::RenderTarget::Generic, roc_reporting::report::RenderTarget::Generic,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),

View file

@ -332,8 +332,7 @@ impl<'a> Surgeries<'a> {
} }
/// Constructs a `Metadata` from a host executable binary, and writes it to disk /// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_elf( pub(crate) fn preprocess_elf_le(
endianness: target_lexicon::Endianness,
host_exe_path: &Path, host_exe_path: &Path,
metadata_path: &Path, metadata_path: &Path,
preprocessed_path: &Path, preprocessed_path: &Path,
@ -479,11 +478,6 @@ pub(crate) fn preprocess_elf(
let text_disassembly_duration = text_disassembly_start.elapsed(); let text_disassembly_duration = text_disassembly_start.elapsed();
let scanning_dynamic_deps_duration;
let platform_gen_start;
let out_mmap = match endianness {
target_lexicon::Endianness::Little => {
let scanning_dynamic_deps_start = Instant::now(); let scanning_dynamic_deps_start = Instant::now();
let ElfDynamicDeps { let ElfDynamicDeps {
@ -496,12 +490,11 @@ pub(crate) fn preprocess_elf(
&exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose,
); );
scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed();
platform_gen_start = Instant::now(); let platform_gen_start = Instant::now();
// TODO little endian let out_mmap = gen_elf_le(
gen_elf_le(
exec_data, exec_data,
&mut md, &mut md,
preprocessed_path, preprocessed_path,
@ -511,15 +504,7 @@ pub(crate) fn preprocess_elf(
dynamic_lib_count, dynamic_lib_count,
shared_lib_index, shared_lib_index,
verbose, 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 platform_gen_duration = platform_gen_start.elapsed(); let platform_gen_duration = platform_gen_start.elapsed();
@ -1743,7 +1728,7 @@ mod tests {
use crate::preprocessed_host_filename; use crate::preprocessed_host_filename;
use indoc::indoc; use indoc::indoc;
use target_lexicon::Triple; use roc_target::Target;
const ELF64_DYNHOST: &[u8] = include_bytes!("../dynhost_benchmarks_elf64") as &[_]; const ELF64_DYNHOST: &[u8] = include_bytes!("../dynhost_benchmarks_elf64") as &[_];
@ -1778,9 +1763,6 @@ mod tests {
fn collect_undefined_symbols_elf() { fn collect_undefined_symbols_elf() {
let object = object::File::parse(ELF64_DYNHOST).unwrap(); 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 let mut keys: Vec<_> = object
.dynamic_symbols() .dynamic_symbols()
.filter(is_roc_undefined) .filter(is_roc_undefined)
@ -1800,7 +1782,7 @@ mod tests {
} }
#[allow(dead_code)] #[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!( let host_zig = indoc!(
r#" r#"
const std = @import("std"); const std = @import("std");
@ -1885,10 +1867,9 @@ mod tests {
panic!("zig build-exe failed"); 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( preprocess_elf_le(
target_lexicon::Endianness::Little,
&dir.join("host"), &dir.join("host"),
&dir.join("metadata"), &dir.join("metadata"),
&preprocessed_host_filename, &preprocessed_host_filename,
@ -1911,12 +1892,10 @@ mod tests {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
#[test] #[test]
fn zig_host_app() { fn zig_host_app() {
use std::str::FromStr;
let dir = tempfile::tempdir().unwrap(); let dir = tempfile::tempdir().unwrap();
let dir = dir.path(); 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")) let output = std::process::Command::new(dir.join("final"))
.current_dir(dir) .current_dir(dir)

View file

@ -1,14 +1,14 @@
use object::write; use object::write;
use object::{Architecture, BinaryFormat, Endianness, SymbolFlags, SymbolKind, SymbolScope}; use object::{Architecture, BinaryFormat, Endianness, SymbolFlags, SymbolKind, SymbolScope};
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_target::Target;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use target_lexicon::Triple;
// TODO: Eventually do this from scratch and in memory instead of with ld. // TODO: Eventually do this from scratch and in memory instead of with ld.
pub fn create_dylib_macho( pub fn create_dylib_macho(
custom_names: &[String], custom_names: &[String],
triple: &Triple, target: Target,
) -> object::read::Result<Vec<u8>> { ) -> object::read::Result<Vec<u8>> {
let dummy_obj_file = tempfile::Builder::new() let dummy_obj_file = tempfile::Builder::new()
.prefix("roc_lib") .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 dummy_lib_file = tmp.path().to_path_buf().with_file_name("libapp.so");
let obj_target = BinaryFormat::MachO; let obj_target = BinaryFormat::MachO;
let obj_arch = match triple.architecture { let obj_arch = match target.architecture() {
target_lexicon::Architecture::X86_64 => Architecture::X86_64, roc_target::Architecture::X86_64 => Architecture::X86_64,
target_lexicon::Architecture::Aarch64(_) => Architecture::Aarch64, roc_target::Architecture::Aarch64 => Architecture::Aarch64,
_ => { _ => {
// We should have verified this via supported() before calling this function // We should have verified this via supported() before calling this function
unreachable!() unreachable!()

View file

@ -1,4 +1,4 @@
use target_lexicon::Triple; use roc_target::{OperatingSystem, Target};
mod elf64; mod elf64;
mod macho; mod macho;
@ -12,11 +12,11 @@ pub(crate) use elf64::create_dylib_elf64;
pub(crate) use pe::APP_DLL; pub(crate) use pe::APP_DLL;
pub fn generate(target: &Triple, custom_names: &[String]) -> object::read::Result<Vec<u8>> { pub fn generate(target: Target, custom_names: &[String]) -> object::read::Result<Vec<u8>> {
match target.binary_format { match target.operating_system() {
target_lexicon::BinaryFormat::Elf => elf64::create_dylib_elf64(custom_names), OperatingSystem::Linux => elf64::create_dylib_elf64(custom_names),
target_lexicon::BinaryFormat::Macho => macho::create_dylib_macho(custom_names, target), OperatingSystem::Mac => macho::create_dylib_macho(custom_names, target),
target_lexicon::BinaryFormat::Coff => Ok(pe::synthetic_dll(custom_names)), OperatingSystem::Windows => Ok(pe::synthetic_dll(custom_names)),
other => unimplemented!("dylib creation for {:?}", other), other => unimplemented!("dylib creation for {:?}", other),
} }
} }
@ -26,8 +26,10 @@ mod tests {
use super::*; use super::*;
use object::Object; 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 custom_names = ["foo".to_string(), "bar".to_string()];
let bytes = generate(target, &custom_names).unwrap(); let bytes = generate(target, &custom_names).unwrap();
@ -75,16 +77,9 @@ mod tests {
#[test] #[test]
fn check_exports_coff_manual() { 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 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 object = object::read::pe::PeFile64::parse(bytes.as_slice()).unwrap();
let exports = { let exports = {

View file

@ -11,11 +11,10 @@ use roc_module::symbol::Interns;
use roc_packaging::cache::RocCacheDir; use roc_packaging::cache::RocCacheDir;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE}; use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use roc_solve::FunctionKind; use roc_solve::FunctionKind;
use roc_target::get_target_triple_str; use roc_target::{Architecture, OperatingSystem, Target};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::mem; use std::mem;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use target_lexicon::Triple;
mod elf; mod elf;
mod macho; mod macho;
@ -31,30 +30,13 @@ pub enum LinkType {
None = 2, 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 { if let LinkType::Executable = link_type {
match target { match target {
Triple { Target::LinuxX64 => true,
architecture: target_lexicon::Architecture::X86_64, Target::WinX64 => true,
operating_system: target_lexicon::OperatingSystem::Linux,
binary_format: target_lexicon::BinaryFormat::Elf,
..
} => true,
// macho support is incomplete // macho support is incomplete
Triple { Target::MacX64 => false,
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,
_ => false, _ => false,
} }
} else { } 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 const PRECOMPILED_HOST_EXT: &str = "rh"; // Short for "roc host"
pub fn preprocessed_host_filename(target: &Triple) -> Option<String> { pub fn preprocessed_host_filename(target: Target) -> String {
roc_target::get_target_triple_str(target).map(|x| format!("{x}.{PRECOMPILED_HOST_EXT}")) format!("{target}.{PRECOMPILED_HOST_EXT}")
} }
fn metadata_file_name(target: &Triple) -> String { fn metadata_file_name(target: Target) -> String {
let target_triple_str = get_target_triple_str(target); format!("metadata_{}.rm", target)
format!("metadata_{}.rm", target_triple_str.unwrap_or("unknown"))
} }
pub fn link_preprocessed_host( pub fn link_preprocessed_host(
target: &Triple, target: Target,
platform_path: &Path, platform_path: &Path,
roc_app_bytes: &[u8], roc_app_bytes: &[u8],
binary_path: &Path, binary_path: &Path,
@ -88,21 +68,20 @@ pub fn link_preprocessed_host(
pub fn generate_stub_lib( pub fn generate_stub_lib(
input_path: &Path, input_path: &Path,
roc_cache_dir: RocCacheDir<'_>, roc_cache_dir: RocCacheDir<'_>,
triple: &Triple, target: Target,
function_kind: FunctionKind, function_kind: FunctionKind,
) -> (PathBuf, PathBuf, Vec<String>) { ) -> (PathBuf, PathBuf, Vec<String>) {
// Note: this should theoretically just be able to load the host, I think. // 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. // 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. // 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. // 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 arena = &bumpalo::Bump::new();
let loaded = roc_load::load_and_monomorphize( let loaded = roc_load::load_and_monomorphize(
arena, arena,
input_path.to_path_buf(), input_path.to_path_buf(),
roc_cache_dir, roc_cache_dir,
LoadConfig { LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::Generic, render: RenderTarget::Generic,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
@ -138,14 +117,14 @@ pub fn generate_stub_lib(
}; };
if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point { 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") platform_path.with_file_name("libapp.obj")
} else { } else {
platform_path.with_file_name("libapp.so") platform_path.with_file_name("libapp.so")
}; };
let stub_dll_symbols = exposed_symbols.stub_dll_symbols(); 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) (platform_path.into(), stub_lib, stub_dll_symbols)
} else { } else {
unreachable!(); unreachable!();
@ -153,11 +132,11 @@ pub fn generate_stub_lib(
} }
pub fn generate_stub_lib_from_loaded( pub fn generate_stub_lib_from_loaded(
target: &Triple, target: Target,
platform_main_roc: &Path, platform_main_roc: &Path,
stub_dll_symbols: &[String], stub_dll_symbols: &[String],
) -> PathBuf { ) -> 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") platform_main_roc.with_file_name("libapp.dll")
} else { } else {
platform_main_roc.with_file_name("libapp.so") 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) { if !stub_lib_is_up_to_date(target, stub_lib_path, stub_dll_symbols) {
let bytes = crate::generate_dylib::generate(target, stub_dll_symbols) let bytes = crate::generate_dylib::generate(target, stub_dll_symbols)
.unwrap_or_else(|e| internal_error!("{e}")); .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) 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); generate_import_library(stub_lib_path, stub_dll_symbols);
} }
} }
@ -336,24 +315,22 @@ fn generate_def_file(custom_names: &[String]) -> Result<String, std::fmt::Error>
Ok(def_file) Ok(def_file)
} }
fn object_matches_target<'a>(target: &Triple, object: &object::File<'a, &'a [u8]>) -> bool { fn object_matches_target<'a>(target: Target, object: &object::File<'a, &'a [u8]>) -> bool {
use target_lexicon::{Architecture as TLA, OperatingSystem as TLO}; match target.architecture() {
Architecture::X86_64 => {
match target.architecture {
TLA::X86_64 => {
if object.architecture() != object::Architecture::X86_64 { if object.architecture() != object::Architecture::X86_64 {
return false; return false;
} }
let target_format = match target.operating_system { let target_format = match target.operating_system() {
TLO::Linux => object::BinaryFormat::Elf, OperatingSystem::Linux => object::BinaryFormat::Elf,
TLO::Windows => object::BinaryFormat::Pe, OperatingSystem::Windows => object::BinaryFormat::Pe,
_ => todo!("surgical linker does not support target {:?}", target), _ => todo!("surgical linker does not support target {:?}", target),
}; };
object.format() == target_format 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), _ => 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 /// 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, /// 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. /// 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) { if !std::path::Path::exists(stub_lib_path) {
return false; 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( pub fn preprocess_host(
target: &Triple, target: Target,
platform_main_roc: &Path, platform_main_roc: &Path,
preprocessed_path: &Path, preprocessed_path: &Path,
shared_lib: &Path, shared_lib: &Path,
stub_dll_symbols: &[String], stub_dll_symbols: &[String],
) { ) {
let metadata_path = platform_main_roc.with_file_name(metadata_file_name(target)); 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") platform_main_roc.with_file_name("dynhost.exe")
} else { } else {
platform_main_roc.with_file_name("dynhost") 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 /// Constructs a `Metadata` from a host executable binary, and writes it to disk
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn preprocess( fn preprocess(
target: &Triple, target: Target,
host_exe_path: &Path, host_exe_path: &Path,
metadata_path: &Path, metadata_path: &Path,
preprocessed_path: &Path, preprocessed_path: &Path,
@ -427,14 +404,9 @@ fn preprocess(
println!("Targeting: {target}"); println!("Targeting: {target}");
} }
let endianness = target match target.arch_os() {
.endianness() (_, OperatingSystem::Linux) => {
.unwrap_or(target_lexicon::Endianness::Little); crate::elf::preprocess_elf_le(
match target.binary_format {
target_lexicon::BinaryFormat::Elf => {
crate::elf::preprocess_elf(
endianness,
host_exe_path, host_exe_path,
metadata_path, metadata_path,
preprocessed_path, preprocessed_path,
@ -444,9 +416,8 @@ fn preprocess(
); );
} }
target_lexicon::BinaryFormat::Macho => { (_, OperatingSystem::Mac) => {
crate::macho::preprocess_macho( crate::macho::preprocess_macho_le(
target,
host_exe_path, host_exe_path,
metadata_path, metadata_path,
preprocessed_path, preprocessed_path,
@ -456,7 +427,7 @@ fn preprocess(
); );
} }
target_lexicon::BinaryFormat::Coff => { (_, OperatingSystem::Windows) => {
crate::pe::preprocess_windows( crate::pe::preprocess_windows(
host_exe_path, host_exe_path,
metadata_path, metadata_path,
@ -468,12 +439,9 @@ fn preprocess(
.unwrap_or_else(|e| internal_error!("{}", e)); .unwrap_or_else(|e| internal_error!("{}", e));
} }
target_lexicon::BinaryFormat::Wasm => { (Architecture::Wasm32, _) => {
todo!("Roc does not yet support web assembly hosts!"); todo!("Roc does not yet support web assembly hosts!");
} }
target_lexicon::BinaryFormat::Unknown => {
internal_error!("Roc does not support unknown host binary formats!");
}
other => { other => {
internal_error!( internal_error!(
concat!( concat!(
@ -492,14 +460,14 @@ fn surgery(
executable_path: &Path, executable_path: &Path,
verbose: bool, verbose: bool,
time: bool, time: bool,
target: &Triple, target: Target,
) { ) {
match target.binary_format { match target.arch_os() {
target_lexicon::BinaryFormat::Elf => { (_, OperatingSystem::Linux) => {
crate::elf::surgery_elf(roc_app_bytes, metadata_path, executable_path, verbose, time); crate::elf::surgery_elf(roc_app_bytes, metadata_path, executable_path, verbose, time);
} }
target_lexicon::BinaryFormat::Macho => { (_, OperatingSystem::Mac) => {
crate::macho::surgery_macho( crate::macho::surgery_macho(
roc_app_bytes, roc_app_bytes,
metadata_path, 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); 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!"); todo!("Roc does not yet support web assembly hosts!");
} }
target_lexicon::BinaryFormat::Unknown => {
internal_error!("Roc does not support unknown host binary formats!");
}
other => { other => {
internal_error!( internal_error!(
concat!( concat!(

View file

@ -17,7 +17,6 @@ use std::{
path::Path, path::Path,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use target_lexicon::Triple;
use crate::{ use crate::{
align_by_constraint, align_to_offset_by_constraint, load_struct_inplace, 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 /// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_macho( pub(crate) fn preprocess_macho_le(
target: &Triple,
host_exe_path: &Path, host_exe_path: &Path,
metadata_path: &Path, metadata_path: &Path,
preprocessed_path: &Path, preprocessed_path: &Path,
@ -544,15 +542,6 @@ pub(crate) fn preprocess_macho(
let text_disassembly_duration = text_disassembly_start.elapsed(); let text_disassembly_duration = text_disassembly_start.elapsed();
let scanning_dynamic_deps_duration;
let platform_gen_start;
let out_mmap = {
match target
.endianness()
.unwrap_or(target_lexicon::Endianness::Little)
{
target_lexicon::Endianness::Little => {
let scanning_dynamic_deps_start = Instant::now(); let scanning_dynamic_deps_start = Instant::now();
// let ElfDynamicDeps { // let ElfDynamicDeps {
@ -564,9 +553,9 @@ pub(crate) fn preprocess_macho(
// &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose, // &exec_obj, &mut md, &app_syms, shared_lib, exec_data, verbose,
// ); // );
scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed(); let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed();
platform_gen_start = Instant::now(); let platform_gen_start = Instant::now();
// TODO little endian // TODO little endian
let macho_load_so_offset = match macho_load_so_offset { let macho_load_so_offset = match macho_load_so_offset {
@ -581,22 +570,13 @@ pub(crate) fn preprocess_macho(
// future this could change? Is there some way to make this more future-proof? // future this could change? Is there some way to make this more future-proof?
md.load_align_constraint = 4096; md.load_align_constraint = 4096;
gen_macho_le( let out_mmap = gen_macho_le(
exec_data, exec_data,
&mut md, &mut md,
preprocessed_path, preprocessed_path,
macho_load_so_offset, macho_load_so_offset,
target,
verbose, 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!");
}
}
};
let platform_gen_duration = platform_gen_start.elapsed(); let platform_gen_duration = platform_gen_start.elapsed();
@ -652,7 +632,6 @@ fn gen_macho_le(
md: &mut Metadata, md: &mut Metadata,
out_filename: &Path, out_filename: &Path,
macho_load_so_offset: usize, macho_load_so_offset: usize,
_target: &Triple,
_verbose: bool, _verbose: bool,
) -> MmapMut { ) -> MmapMut {
// Just adding some extra context/useful info here. // Just adding some extra context/useful info here.

View file

@ -1795,7 +1795,7 @@ mod test {
} }
let preprocessed_host_filename = let preprocessed_host_filename =
dir.join(preprocessed_host_filename(&Triple::host()).unwrap()); dir.join(preprocessed_host_filename(Triple::host().into()));
preprocess_windows( preprocess_windows(
&dir.join("host.exe"), &dir.join("host.exe"),

View file

@ -15,18 +15,16 @@ use roc_repl_eval::eval::jit_to_ast;
use roc_repl_eval::gen::{format_answer, ReplOutput}; use roc_repl_eval::gen::{format_answer, ReplOutput};
use roc_repl_eval::{ReplApp, ReplAppMemory}; use roc_repl_eval::{ReplApp, ReplAppMemory};
use roc_std::RocStr; 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::pretty_print::{name_and_print_var, DebugPrint};
use roc_types::subs::Subs; use roc_types::subs::Subs;
use target_lexicon::Triple;
pub fn eval_llvm( pub fn eval_llvm(
mut loaded: MonomorphizedModule<'_>, mut loaded: MonomorphizedModule<'_>,
target: &Triple, target: Target,
opt_level: OptLevel, opt_level: OptLevel,
) -> Option<ReplOutput> { ) -> Option<ReplOutput> {
let arena = Bump::new(); let arena = Bump::new();
let target_info = TargetInfo::from(target);
debug_assert_eq!(loaded.exposed_to_host.top_level_values.len(), 1); debug_assert_eq!(loaded.exposed_to_host.top_level_values.len(), 1);
let (main_fn_symbol, main_fn_var) = loaded let (main_fn_symbol, main_fn_var) = loaded
@ -81,7 +79,7 @@ pub fn eval_llvm(
&subs, &subs,
&interns, &interns,
layout_interner.into_global().fork(), layout_interner.into_global().fork(),
target_info, target,
); );
let expr_str = format_answer(&arena, expr).to_string(); let expr_str = format_answer(&arena, expr).to_string();
@ -180,12 +178,10 @@ impl ReplAppMemory for CliMemory {
)] )]
fn mono_module_to_dylib_llvm<'a>( fn mono_module_to_dylib_llvm<'a>(
arena: &'a Bump, arena: &'a Bump,
target: &Triple, target: Target,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
opt_level: OptLevel, opt_level: OptLevel,
) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> { ) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> {
let target_info = TargetInfo::from(target);
let MonomorphizedModule { let MonomorphizedModule {
procedures, procedures,
host_exposed_lambda_sets, host_exposed_lambda_sets,
@ -217,7 +213,7 @@ fn mono_module_to_dylib_llvm<'a>(
context: &context, context: &context,
interns, interns,
module, module,
target_info, target,
mode: LlvmBackendMode::GenTest, // so roc_panic is generated mode: LlvmBackendMode::GenTest, // so roc_panic is generated
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
@ -286,7 +282,7 @@ fn mono_module_to_dylib_llvm<'a>(
)] )]
fn mono_module_to_dylib_asm<'a>( fn mono_module_to_dylib_asm<'a>(
arena: &'a Bump, arena: &'a Bump,
target: &Triple, target: Target,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
_opt_level: OptLevel, _opt_level: OptLevel,
) -> Result<(libloading::Library, &'a str, Subs, STLayoutInterner<'a>), libloading::Error> { ) -> 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 app_o_file = dir.path().join("app.o");
let _target_info = TargetInfo::from(target);
let MonomorphizedModule { let MonomorphizedModule {
module_id, module_id,
procedures, procedures,
@ -317,14 +311,8 @@ fn mono_module_to_dylib_asm<'a>(
mode: roc_gen_dev::AssemblyBackendMode::Repl, mode: roc_gen_dev::AssemblyBackendMode::Repl,
}; };
let target = target_lexicon::Triple::host(); let module_object =
let module_object = roc_gen_dev::build_module( roc_gen_dev::build_module(&env, &mut interns, &mut layout_interner, target, procedures);
&env,
&mut interns,
&mut layout_interner,
&target,
procedures,
);
let module_out = module_object let module_out = module_object
.write() .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"); roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
let (mut child, dylib_path) = roc_build::link::link( let (mut child, dylib_path) = roc_build::link::link(
&target, target,
app_o_file.clone(), app_o_file.clone(),
// Long term we probably want a smarter way to link in zig builtins. // 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. // With the current method all methods are kept and it adds about 100k to all outputs.

View file

@ -10,7 +10,7 @@ use roc_repl_ui::colors::{CYAN, END_COL};
use roc_repl_ui::repl_state::{ReplAction, ReplState}; use roc_repl_ui::repl_state::{ReplAction, ReplState};
use roc_repl_ui::{format_output, is_incomplete, CONT_PROMPT, PROMPT, SHORT_INSTRUCTIONS, TIPS}; 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_reporting::report::{ANSI_STYLE_CODES, DEFAULT_PALETTE};
use roc_target::TargetInfo; use roc_target::Target;
use rustyline::highlight::{Highlighter, PromptInfo}; use rustyline::highlight::{Highlighter, PromptInfo};
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator}; use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
use rustyline_derive::{Completer, Helper, Hinter}; use rustyline_derive::{Completer, Helper, Hinter};
@ -46,8 +46,7 @@ pub fn main() -> i32 {
let mut editor = Editor::<ReplHelper>::new(); let mut editor = Editor::<ReplHelper>::new();
let repl_helper = ReplHelper::default(); let repl_helper = ReplHelper::default();
editor.set_helper(Some(repl_helper)); editor.set_helper(Some(repl_helper));
let target = Triple::host(); let target = Triple::host().into();
let target_info = TargetInfo::from(&target);
let mut arena = Bump::new(); let mut arena = Bump::new();
loop { loop {
@ -63,9 +62,9 @@ pub fn main() -> i32 {
.state; .state;
arena.reset(); 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 } => { 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! // If there was no output, don't print a blank line!
// (This happens for something like a type annotation.) // (This happens for something like a type annotation.)
if !output.is_empty() { if !output.is_empty() {
@ -104,7 +103,7 @@ pub fn main() -> i32 {
pub fn evaluate( pub fn evaluate(
opt_mono: Option<MonomorphizedModule<'_>>, opt_mono: Option<MonomorphizedModule<'_>>,
problems: Problems, problems: Problems,
target: &Triple, target: Target,
) -> String { ) -> String {
let opt_output = opt_mono.and_then(|mono| eval_llvm(mono, target, OptLevel::Normal)); let opt_output = opt_mono.and_then(|mono| eval_llvm(mono, target, OptLevel::Normal));
format_output(ANSI_STYLE_CODES, opt_output, problems) format_output(ANSI_STYLE_CODES, opt_output, problems)

View file

@ -16,7 +16,7 @@ use roc_mono::layout::{
use roc_parse::ast::{AssignedField, Collection, Expr, Pattern, StrLiteral}; use roc_parse::ast::{AssignedField, Collection, Expr, Pattern, StrLiteral};
use roc_region::all::{Loc, Region}; use roc_region::all::{Loc, Region};
use roc_std::RocDec; use roc_std::RocDec;
use roc_target::TargetInfo; use roc_target::Target;
use roc_types::subs::{ use roc_types::subs::{
Content, FlatType, GetSubsSlice, RecordFields, Subs, TagExt, TupleElems, UnionTags, Variable, Content, FlatType, GetSubsSlice, RecordFields, Subs, TagExt, TupleElems, UnionTags, Variable,
}; };
@ -26,7 +26,7 @@ use crate::{ReplApp, ReplAppMemory};
struct Env<'a, 'env> { struct Env<'a, 'env> {
arena: &'a Bump, arena: &'a Bump,
subs: &'env Subs, subs: &'env Subs,
target_info: TargetInfo, target: Target,
interns: &'a Interns, interns: &'a Interns,
layout_cache: LayoutCache<'a>, layout_cache: LayoutCache<'a>,
} }
@ -49,14 +49,14 @@ pub fn jit_to_ast<'a, A: ReplApp<'a>>(
subs: &Subs, subs: &Subs,
interns: &'a Interns, interns: &'a Interns,
layout_interner: TLLayoutInterner<'a>, layout_interner: TLLayoutInterner<'a>,
target_info: TargetInfo, target: Target,
) -> Expr<'a> { ) -> Expr<'a> {
let mut env = Env { let mut env = Env {
arena, arena,
subs, subs,
target_info, target,
interns, interns,
layout_cache: LayoutCache::new(layout_interner, target_info), layout_cache: LayoutCache::new(layout_interner, target),
}; };
match layout { match layout {
@ -338,7 +338,7 @@ fn tag_id_from_recursive_ptr<'a, M: ReplAppMemory>(
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
rec_addr: usize, rec_addr: usize,
) -> (i64, 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 { if tag_in_ptr {
let (tag_id, data_addr) = mem.deref_pointer_with_tag_id(rec_addr); 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)) 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, Some(string) => string,
None => Expr::REPL_RUNTIME_CRASH, None => Expr::REPL_RUNTIME_CRASH,
} }
@ -628,8 +628,8 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
} }
(_, LayoutRepr::Builtin(Builtin::List(elem_layout))) => { (_, LayoutRepr::Builtin(Builtin::List(elem_layout))) => {
let elem_addr = mem.deref_usize(addr); let elem_addr = mem.deref_usize(addr);
let len = mem.deref_usize(addr + 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_info.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) list_to_ast(env, mem, elem_addr, len, elem_layout, raw_content)
} }

View file

@ -12,7 +12,7 @@ use roc_parse::ast::Expr;
use roc_region::all::LineInfo; use roc_region::all::LineInfo;
use roc_reporting::report::{can_problem, type_problem, RocDocAllocator}; use roc_reporting::report::{can_problem, type_problem, RocDocAllocator};
use roc_solve::FunctionKind; use roc_solve::FunctionKind;
use roc_target::TargetInfo; use roc_target::Target;
#[derive(Debug)] #[derive(Debug)]
pub struct ReplOutput { pub struct ReplOutput {
@ -49,7 +49,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
arena: &'a Bump, arena: &'a Bump,
defs: I, defs: I,
expr: &str, expr: &str,
target_info: TargetInfo, target: Target,
palette: Palette, palette: Palette,
) -> (Option<MonomorphizedModule<'a>>, Problems) { ) -> (Option<MonomorphizedModule<'a>>, Problems) {
let filename = PathBuf::from("replfile.roc"); let filename = PathBuf::from("replfile.roc");
@ -62,7 +62,7 @@ pub fn compile_to_mono<'a, 'i, I: Iterator<Item = &'i str>>(
src_dir, src_dir,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()), RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LoadConfig { LoadConfig {
target_info, target,
function_kind: FunctionKind::LambdaSet, function_kind: FunctionKind::LambdaSet,
render: roc_reporting::report::RenderTarget::ColorTerminal, render: roc_reporting::report::RenderTarget::ColorTerminal,
palette, palette,

View file

@ -1,7 +1,7 @@
//! Provides the functionality for the REPL to evaluate Roc expressions. //! Provides the functionality for the REPL to evaluate Roc expressions.
use roc_parse::ast::Expr; use roc_parse::ast::Expr;
use roc_std::RocDec; use roc_std::RocDec;
use roc_target::TargetInfo; use roc_target::Target;
pub mod eval; pub mod eval;
pub mod gen; pub mod gen;
@ -28,7 +28,7 @@ pub trait ReplApp<'a> {
/// When the executed code calls roc_panic, this function will return None /// When the executed code calls roc_panic, this function will return None
fn call_function_returns_roc_str<T, F>( fn call_function_returns_roc_str<T, F>(
&mut self, &mut self,
target_info: TargetInfo, target: Target,
main_fn_name: &str, main_fn_name: &str,
transform: F, transform: F,
) -> Option<T> ) -> Option<T>
@ -36,7 +36,7 @@ pub trait ReplApp<'a> {
F: Fn(&'a Self::Memory, usize) -> T, F: Fn(&'a Self::Memory, usize) -> T,
Self::Memory: 'a, 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::Bytes4 => 12,
roc_target::PtrWidth::Bytes8 => 24, roc_target::PtrWidth::Bytes8 => 24,
}; };

View file

@ -1,7 +1,7 @@
use roc_parse::ast::Expr; use roc_parse::ast::Expr;
use roc_repl_eval::{ReplApp, ReplAppMemory}; use roc_repl_eval::{ReplApp, ReplAppMemory};
use roc_std::RocStr; use roc_std::RocStr;
use roc_target::TargetInfo; use roc_target::Target;
pub(crate) struct ExpectMemory { pub(crate) struct ExpectMemory {
pub(crate) start: *const u8, pub(crate) start: *const u8,
@ -118,7 +118,7 @@ impl<'a> ReplApp<'a> for ExpectReplApp<'a> {
fn call_function_returns_roc_str<T, F>( fn call_function_returns_roc_str<T, F>(
&mut self, &mut self,
_target_info: TargetInfo, _target: Target,
main_fn_name: &str, main_fn_name: &str,
transform: F, transform: F,
) -> Option<T> ) -> Option<T>

View file

@ -8,7 +8,7 @@ use {
}, },
roc_parse::ast::Expr, roc_parse::ast::Expr,
roc_repl_eval::{eval::jit_to_ast, ReplAppMemory}, roc_repl_eval::{eval::jit_to_ast, ReplAppMemory},
roc_target::TargetInfo, roc_target::Target,
roc_types::subs::{Subs, Variable}, roc_types::subs::{Subs, Variable},
}; };
@ -23,7 +23,7 @@ use app::{ExpectMemory, ExpectReplApp};
#[cfg(not(windows))] #[cfg(not(windows))]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn get_values<'a>( pub fn get_values<'a>(
target_info: TargetInfo, target: Target,
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
subs: &Subs, subs: &Subs,
interns: &'a Interns, interns: &'a Interns,
@ -58,7 +58,7 @@ pub fn get_values<'a>(
app.offset = start; app.offset = start;
// TODO: pass layout_cache to jit_to_ast directly // 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 layout = layout_cache.from_var(arena, variable, subs).unwrap();
let proc_layout = ProcLayout { let proc_layout = ProcLayout {
@ -76,7 +76,7 @@ pub fn get_values<'a>(
subs, subs,
interns, interns,
layout_interner.fork(), layout_interner.fork(),
target_info, target,
); );
app.offset += layout_cache.interner.stack_size_and_alignment(layout).0 as usize; 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 crate::run::expect_mono_module_to_dylib;
use super::*;
fn run_expect_test(source: &str, expected: &str) { fn run_expect_test(source: &str, expected: &str) {
let arena = bumpalo::Bump::new(); let arena = bumpalo::Bump::new();
let arena = &arena; let arena = &arena;
let triple = Triple::host(); let target = Triple::host().into();
let target = &triple;
let opt_level = roc_mono::ir::OptLevel::Normal; let opt_level = roc_mono::ir::OptLevel::Normal;
let target_info = TargetInfo::from(target);
let function_kind = FunctionKind::LambdaSet; let function_kind = FunctionKind::LambdaSet;
// Step 1: compile the app and generate the .o file // Step 1: compile the app and generate the .o file
@ -122,7 +118,7 @@ mod test {
std::fs::write(&filename, source).unwrap(); std::fs::write(&filename, source).unwrap();
let load_config = LoadConfig { let load_config = LoadConfig {
target_info, target,
function_kind, function_kind,
render: RenderTarget::ColorTerminal, render: RenderTarget::ColorTerminal,
palette: DEFAULT_PALETTE, palette: DEFAULT_PALETTE,
@ -150,13 +146,8 @@ mod test {
let interns = loaded.interns.clone(); let interns = loaded.interns.clone();
let (dy_lib, expects_by_module, layout_interner) = expect_mono_module_to_dylib( let (dy_lib, expects_by_module, layout_interner) =
arena, expect_mono_module_to_dylib(arena, target, loaded, opt_level, LlvmBackendMode::CliTest)
target.clone(),
loaded,
opt_level,
LlvmBackendMode::CliTest,
)
.unwrap(); .unwrap();
let arena = &bumpalo::Bump::new(); let arena = &bumpalo::Bump::new();

View file

@ -26,9 +26,8 @@ use roc_mono::{
}; };
use roc_region::all::Region; use roc_region::all::Region;
use roc_reporting::{error::expect::Renderer, report::RenderTarget}; use roc_reporting::{error::expect::Renderer, report::RenderTarget};
use roc_target::TargetInfo; use roc_target::Target;
use roc_types::subs::Subs; use roc_types::subs::Subs;
use target_lexicon::Triple;
pub struct ExpectMemory<'a> { pub struct ExpectMemory<'a> {
ptr: *mut u8, ptr: *mut u8,
@ -469,7 +468,7 @@ fn render_expect_failure<'a>(
offset: usize, offset: usize,
) -> std::io::Result<usize> { ) -> std::io::Result<usize> {
// we always run programs as the host // 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 frame = ExpectFrame::at_offset(start, offset);
let module_id = frame.module_id; let module_id = frame.module_id;
@ -487,7 +486,7 @@ fn render_expect_failure<'a>(
let symbols = split_expect_lookups(&data.subs, current); let symbols = split_expect_lookups(&data.subs, current);
let (offset, expressions, variables) = crate::get_values( let (offset, expressions, variables) = crate::get_values(
target_info, target,
arena, arena,
&data.subs, &data.subs,
interns, interns,
@ -613,7 +612,7 @@ pub struct ExpectFunctions<'a> {
pub fn expect_mono_module_to_dylib<'a>( pub fn expect_mono_module_to_dylib<'a>(
arena: &'a Bump, arena: &'a Bump,
target: Triple, target: Target,
loaded: MonomorphizedModule<'a>, loaded: MonomorphizedModule<'a>,
opt_level: OptLevel, opt_level: OptLevel,
mode: LlvmBackendMode, mode: LlvmBackendMode,
@ -625,8 +624,6 @@ pub fn expect_mono_module_to_dylib<'a>(
), ),
libloading::Error, libloading::Error,
> { > {
let target_info = TargetInfo::from(&target);
let MonomorphizedModule { let MonomorphizedModule {
toplevel_expects, toplevel_expects,
procedures, procedures,
@ -638,7 +635,7 @@ pub fn expect_mono_module_to_dylib<'a>(
let context = Context::create(); let context = Context::create();
let builder = context.create_builder(); let builder = context.create_builder();
let module = arena.alloc(roc_gen_llvm::llvm::build::module_from_builtins( let module = arena.alloc(roc_gen_llvm::llvm::build::module_from_builtins(
&target, &context, "", target, &context, "",
)); ));
let module = arena.alloc(module); let module = arena.alloc(module);
@ -656,7 +653,7 @@ pub fn expect_mono_module_to_dylib<'a>(
context: &context, context: &context,
interns, interns,
module, module,
target_info, target,
mode, mode,
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
@ -753,6 +750,6 @@ pub fn expect_mono_module_to_dylib<'a>(
env.module.print_to_file(path).unwrap(); 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)) .map(|dy_lib| (dy_lib, modules_expects, layout_interner))
} }

View file

@ -4,7 +4,6 @@ use roc_repl_cli::{evaluate, ReplHelper};
use roc_repl_ui::is_incomplete; use roc_repl_ui::is_incomplete;
use roc_repl_ui::repl_state::{ReplAction, ReplState}; use roc_repl_ui::repl_state::{ReplAction, ReplState};
use roc_reporting::report::DEFAULT_PALETTE; use roc_reporting::report::DEFAULT_PALETTE;
use roc_target::TargetInfo;
use rustyline::Editor; use rustyline::Editor;
use target_lexicon::Triple; use target_lexicon::Triple;
@ -128,9 +127,8 @@ fn partial_record_definition() {
fn tips() { fn tips() {
assert!(!is_incomplete("")); assert!(!is_incomplete(""));
let arena = Bump::new(); let arena = Bump::new();
let target = Triple::host(); let target = Triple::host().into();
let target_info = TargetInfo::from(&target); let action = ReplState::default().step(&arena, "", target, DEFAULT_PALETTE);
let action = ReplState::default().step(&arena, "", target_info, DEFAULT_PALETTE);
assert!(matches!(action, ReplAction::Help)); assert!(matches!(action, ReplAction::Help));
} }
@ -142,9 +140,8 @@ fn standalone_annotation() {
incomplete(&mut input); incomplete(&mut input);
assert!(!is_incomplete(&input)); assert!(!is_incomplete(&input));
let arena = Bump::new(); let arena = Bump::new();
let target = Triple::host(); let target = Triple::host().into();
let target_info = TargetInfo::from(&target); let action = state.step(&arena, &input, target, DEFAULT_PALETTE);
let action = state.step(&arena, &input, target_info, DEFAULT_PALETTE);
assert!(matches!(action, ReplAction::Nothing)); assert!(matches!(action, ReplAction::Nothing));
} }
@ -153,16 +150,15 @@ fn standalone_annotation() {
fn complete(input: &str, state: &mut ReplState, expected_start: &str) { fn complete(input: &str, state: &mut ReplState, expected_start: &str) {
assert!(!is_incomplete(input)); assert!(!is_incomplete(input));
let arena = Bump::new(); let arena = Bump::new();
let target = Triple::host(); let target = Triple::host().into();
let target_info = TargetInfo::from(&target); let action = state.step(&arena, input, target, DEFAULT_PALETTE);
let action = state.step(&arena, input, target_info, DEFAULT_PALETTE);
let repl_helper = ReplHelper::default(); let repl_helper = ReplHelper::default();
let mut editor = Editor::<ReplHelper>::new(); let mut editor = Editor::<ReplHelper>::new();
editor.set_helper(Some(repl_helper)); editor.set_helper(Some(repl_helper));
match action { match action {
ReplAction::Eval { opt_mono, problems } => { ReplAction::Eval { opt_mono, problems } => {
let string = evaluate(opt_mono, problems, &target); let string = evaluate(opt_mono, problems, target);
let escaped = let escaped =
std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap()) std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap())
.unwrap(); .unwrap();
@ -190,16 +186,15 @@ fn incomplete(input: &mut String) {
fn error(input: &str, state: &mut ReplState, expected_step_result: String) { fn error(input: &str, state: &mut ReplState, expected_step_result: String) {
assert!(!is_incomplete(input)); assert!(!is_incomplete(input));
let arena = Bump::new(); let arena = Bump::new();
let target = Triple::host(); let target = Triple::host().into();
let target_info = TargetInfo::from(&target); let action = state.step(&arena, input, target, DEFAULT_PALETTE);
let action = state.step(&arena, input, target_info, DEFAULT_PALETTE);
let repl_helper = ReplHelper::default(); let repl_helper = ReplHelper::default();
let mut editor = Editor::<ReplHelper>::new(); let mut editor = Editor::<ReplHelper>::new();
editor.set_helper(Some(repl_helper)); editor.set_helper(Some(repl_helper));
match action { match action {
ReplAction::Eval { opt_mono, problems } => { ReplAction::Eval { opt_mono, problems } => {
let string = evaluate(opt_mono, problems, &target); let string = evaluate(opt_mono, problems, target);
let escaped = let escaped =
std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap()) std::string::String::from_utf8(strip_ansi_escapes::strip(string.trim()).unwrap())
.unwrap(); .unwrap();

View file

@ -11,7 +11,7 @@ use roc_parse::{join_alias_to_body, join_ann_to_body};
use roc_region::all::Loc; use roc_region::all::Loc;
use roc_repl_eval::gen::{compile_to_mono, Problems}; use roc_repl_eval::gen::{compile_to_mono, Problems};
use roc_reporting::report::Palette; use roc_reporting::report::Palette;
use roc_target::TargetInfo; use roc_target::Target;
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
struct PastDef { struct PastDef {
@ -54,7 +54,7 @@ impl ReplState {
&mut self, &mut self,
arena: &'a Bump, arena: &'a Bump,
line: &str, line: &str,
target_info: TargetInfo, target: Target,
palette: Palette, palette: Palette,
) -> ReplAction<'a> { ) -> ReplAction<'a> {
let pending_past_def; let pending_past_def;
@ -170,7 +170,7 @@ impl ReplState {
arena, arena,
self.past_defs.iter().map(|def| def.src.as_str()), self.past_defs.iter().map(|def| def.src.as_str()),
src, src,
target_info, target,
palette, palette,
); );

View file

@ -16,7 +16,7 @@ use roc_repl_ui::{
repl_state::{ReplAction, ReplState}, repl_state::{ReplAction, ReplState},
TIPS, TIPS,
}; };
use roc_target::TargetInfo; use roc_target::Target;
use roc_types::pretty_print::{name_and_print_var, DebugPrint}; use roc_types::pretty_print::{name_and_print_var, DebugPrint};
use crate::{js_create_app, js_get_result_and_memory, js_run_app}; 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(); let arena = &Bump::new();
// Compile the app // Compile the app
let target_info = TargetInfo::default_wasm32(); let target = Target::Wasm32;
// Advance the REPL state machine // Advance the REPL state machine
let action = REPL_STATE.with(|repl_state_cell| { let action = REPL_STATE.with(|repl_state_cell| {
let mut repl_state = repl_state_cell.borrow_mut(); 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 // 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::Nothing => String::new(),
ReplAction::Eval { opt_mono, problems } => { ReplAction::Eval { opt_mono, problems } => {
let opt_output = match opt_mono { 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, None => None,
}; };
@ -217,7 +217,7 @@ pub async fn entrypoint_from_js(src: String) -> String {
async fn eval_wasm<'a>( async fn eval_wasm<'a>(
arena: &'a Bump, arena: &'a Bump,
target_info: TargetInfo, target: Target,
mono: MonomorphizedModule<'a>, mono: MonomorphizedModule<'a>,
) -> Option<ReplOutput> { ) -> Option<ReplOutput> {
let MonomorphizedModule { let MonomorphizedModule {
@ -311,7 +311,7 @@ async fn eval_wasm<'a>(
&subs, &subs,
&interns, &interns,
layout_interner.into_global().fork(), layout_interner.into_global().fork(),
target_info, target,
); );
// Transform the Expr to a string // Transform the Expr to a string

View file

@ -14,11 +14,11 @@ fn build_host() {
roc_command_utils::root_dir().join("crates/valgrind/zig-platform/main.roc"); roc_command_utils::root_dir().join("crates/valgrind/zig-platform/main.roc");
// tests always run on the host // 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 // the preprocessed host is stored beside the platform's main.roc
let preprocessed_host_path = 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 // valgrind does not support avx512 yet: https://bugs.kde.org/show_bug.cgi?id=383010
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@ -28,7 +28,7 @@ fn build_host() {
build_and_preprocess_host( build_and_preprocess_host(
roc_mono::ir::OptLevel::Normal, roc_mono::ir::OptLevel::Normal,
&target, target,
&platform_main_roc, &platform_main_roc,
&preprocessed_host_path, &preprocessed_host_path,
roc_linker::ExposedSymbols { roc_linker::ExposedSymbols {