Use roc_target over target_lexicon

Tailors a target class for our needs.
Replaces tons of uses across the entire compiler.
This is a base for later adding new targets like thumb.
This commit is contained in:
Brendan Hansknecht 2024-03-21 21:54:58 -07:00
parent 185262510c
commit 6dc5bfb1b7
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
72 changed files with 1008 additions and 1371 deletions

1
Cargo.lock generated
View file

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

View file

@ -23,7 +23,7 @@ use roc_mono::ir::OptLevel;
use roc_packaging::cache::RocCacheDir;
use roc_packaging::tarball::Compression;
use roc_reporting::report::ANSI_STYLE_CODES;
use roc_target::Target;
use roc_target::{Architecture, Target};
use std::env;
use std::ffi::{CString, OsStr, OsString};
use std::io;
@ -33,7 +33,6 @@ use std::path::{Path, PathBuf};
use std::process;
use std::time::{Duration, Instant};
use strum::IntoEnumIterator;
use target_lexicon::{Architecture, Triple};
#[cfg(not(target_os = "linux"))]
use tempfile::TempDir;
@ -442,7 +441,7 @@ fn opt_level_from_flags(matches: &ArgMatches) -> OptLevel {
}
#[cfg(windows)]
pub fn test(_matches: &ArgMatches, _triple: Triple) -> io::Result<i32> {
pub fn test(_matches: &ArgMatches, _target: Target) -> io::Result<i32> {
todo!("running tests does not work on windows right now")
}
@ -454,11 +453,10 @@ struct ModuleTestResults {
}
#[cfg(not(windows))]
pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
pub fn test(matches: &ArgMatches, target: Target) -> io::Result<i32> {
use roc_build::program::report_problems_monomorphized;
use roc_load::{ExecutionMode, FunctionKind, LoadConfig, LoadMonomorphizedError};
use roc_packaging::cache;
use roc_target::TargetInfo;
let start_time = Instant::now();
let arena = Bump::new();
@ -495,14 +493,12 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
}
let arena = &arena;
let target = &triple;
let target_info = TargetInfo::from(target);
// TODO may need to determine this dynamically based on dev builds.
let function_kind = FunctionKind::LambdaSet;
// Step 1: compile the app and generate the .o file
let load_config = LoadConfig {
target_info,
target,
function_kind,
// TODO: expose this from CLI?
render: roc_reporting::report::RenderTarget::ColorTerminal,
@ -536,7 +532,7 @@ pub fn test(matches: &ArgMatches, triple: Triple) -> io::Result<i32> {
let (dyn_lib, expects_by_module, layout_interner) =
roc_repl_expect::run::expect_mono_module_to_dylib(
arena,
target.clone(),
target,
loaded,
opt_level,
LlvmBackendMode::CliTest,
@ -673,7 +669,7 @@ pub fn build(
matches: &ArgMatches,
subcommands: &[String],
config: BuildConfig,
triple: Triple,
target: Target,
out_path: Option<&Path>,
roc_cache_dir: RocCacheDir<'_>,
link_type: LinkType,
@ -784,7 +780,7 @@ pub fn build(
// Note: This allows using `--dev` with `--optimize`.
// This means frontend optimizations and dev backend.
let code_gen_backend = if matches.get_flag(FLAG_DEV) {
if matches!(triple.architecture, Architecture::Wasm32) {
if matches!(target.architecture(), Architecture::Wasm32) {
CodeGenBackend::Wasm
} else {
CodeGenBackend::Assembly(AssemblyBackendMode::Binary)
@ -818,7 +814,7 @@ pub fn build(
let linking_strategy = if wasm_dev_backend {
LinkingStrategy::Additive
} else if !roc_linker::supported(link_type, &triple)
} else if !roc_linker::supported(link_type, target)
|| matches.get_one::<String>(FLAG_LINKER).map(|s| s.as_str()) == Some("legacy")
{
LinkingStrategy::Legacy
@ -827,8 +823,8 @@ pub fn build(
};
let prebuilt = {
let cross_compile = triple != Triple::host();
let targeting_wasm = matches!(triple.architecture, Architecture::Wasm32);
let cross_compile = target != Target::default();
let targeting_wasm = matches!(target.architecture(), Architecture::Wasm32);
matches.get_flag(FLAG_PREBUILT) ||
// When compiling for a different target, assume a prebuilt platform.
@ -862,11 +858,11 @@ pub fn build(
fuzz,
};
let load_config = standard_load_config(&triple, build_ordering, threading);
let load_config = standard_load_config(target, build_ordering, threading);
let res_binary_path = build_file(
&arena,
&triple,
target,
path.to_owned(),
code_gen_options,
emit_timings,
@ -933,7 +929,7 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap());
roc_run(&arena, opt_level, triple, args, bytes, expect_metadata)
roc_run(&arena, opt_level, target, args, bytes, expect_metadata)
}
BuildAndRunIfNoErrors => {
if problems.fatally_errored {
@ -968,7 +964,7 @@ pub fn build(
// ManuallyDrop will leak the bytes because we don't drop manually
let bytes = &ManuallyDrop::new(std::fs::read(&binary_path).unwrap());
roc_run(&arena, opt_level, triple, args, bytes, expect_metadata)
roc_run(&arena, opt_level, target, args, bytes, expect_metadata)
}
}
}
@ -982,12 +978,12 @@ pub fn build(
fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
arena: &Bump,
opt_level: OptLevel,
triple: Triple,
target: Target,
args: I,
binary_bytes: &[u8],
expect_metadata: ExpectMetadata,
) -> io::Result<i32> {
match triple.architecture {
match target.architecture() {
Architecture::Wasm32 => {
let executable = roc_run_executable_file_path(binary_bytes)?;
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_load::{FunctionKind, LoadingProblem, Threading};
use roc_packaging::cache::{self, RocCacheDir};
use roc_target::{get_target_triple_str, Target};
use roc_target::Target;
use std::fs::{self, FileType};
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
@ -49,7 +49,7 @@ fn main() -> io::Result<()> {
&matches,
&subcommands,
BuildConfig::BuildAndRunIfNoErrors,
Triple::host(),
Triple::host().into(),
None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable,
@ -64,7 +64,7 @@ fn main() -> io::Result<()> {
matches,
&subcommands,
BuildConfig::BuildAndRun,
Triple::host(),
Triple::host().into(),
None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable,
@ -77,7 +77,7 @@ fn main() -> io::Result<()> {
}
Some((CMD_TEST, matches)) => {
if matches.contains_id(ROC_FILE) {
test(matches, Triple::host())
test(matches, Triple::host().into())
} else {
eprintln!("What .roc file do you want to test? Specify it at the end of the `roc test` command.");
@ -90,7 +90,7 @@ fn main() -> io::Result<()> {
matches,
&subcommands,
BuildConfig::BuildAndRunIfNoErrors,
Triple::host(),
Triple::host().into(),
None,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
LinkType::Executable,
@ -130,7 +130,7 @@ fn main() -> io::Result<()> {
roc_linker::generate_stub_lib(
input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
&target.to_triple(),
target,
function_kind,
);
Ok(0)
@ -142,24 +142,22 @@ fn main() -> io::Result<()> {
.and_then(|s| Target::from_str(s).ok())
.unwrap_or_default();
let triple = target.to_triple();
let function_kind = FunctionKind::LambdaSet;
let (platform_path, stub_lib, stub_dll_symbols) = roc_linker::generate_stub_lib(
input_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
&triple,
target,
function_kind,
);
// TODO: pipeline the executable location through here.
// Currently it is essentally hardcoded as platform_path/dynhost.
roc_linker::preprocess_host(
&triple,
target,
&platform_path.with_file_name("main.roc"),
// The target triple string must be derived from the triple to convert from the generic
// `system` target to the exact specific target.
&platform_path
.with_file_name(format!("{}.rh", get_target_triple_str(&triple).unwrap())),
&platform_path.with_file_name(format!("{}.rh", target)),
&stub_lib,
&stub_dll_symbols,
);
@ -184,7 +182,7 @@ fn main() -> io::Result<()> {
matches,
&subcommands,
BuildConfig::BuildOnly,
target.to_triple(),
target,
out_path,
RocCacheDir::Persistent(cache::roc_cache_dir().as_path()),
link_type,

View file

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

View file

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

View file

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

View file

@ -1,5 +1,5 @@
use roc_module::symbol::Symbol;
use roc_target::TargetInfo;
use roc_target::Target;
use std::ops::Index;
#[derive(Debug, Default, Copy, Clone)]
@ -38,7 +38,7 @@ impl FloatWidth {
}
}
pub const fn alignment_bytes(&self, target_info: TargetInfo) -> u32 {
pub const fn alignment_bytes(&self, target: Target) -> u32 {
use roc_target::Architecture::*;
use FloatWidth::*;
@ -47,7 +47,7 @@ impl FloatWidth {
// the compiler is targeting (e.g. what the Roc code will be compiled to).
match self {
F32 => 4,
F64 => match target_info.architecture {
F64 => match target.architecture() {
X86_64 | Aarch64 | Wasm32 => 8,
X86_32 | Aarch32 => 4,
},
@ -107,7 +107,7 @@ impl IntWidth {
}
}
pub const fn alignment_bytes(&self, target_info: TargetInfo) -> u32 {
pub const fn alignment_bytes(&self, target: Target) -> u32 {
use roc_target::Architecture;
use IntWidth::*;
@ -118,7 +118,7 @@ impl IntWidth {
U8 | I8 => 1,
U16 | I16 => 2,
U32 | I32 => 4,
U64 | I64 => match target_info.architecture {
U64 | I64 => match target.architecture() {
Architecture::X86_64
| Architecture::Aarch64
| Architecture::Aarch32
@ -131,7 +131,7 @@ impl IntWidth {
//
// however, rust does not always think that this is true
// Our alignmets here are correct, but they will not match rust/zig/llvm until they update to llvm version 18.
match target_info.architecture {
match target.architecture() {
Architecture::X86_64 | Architecture::Aarch64 | Architecture::X86_32 => 16,
Architecture::Aarch32 | Architecture::Wasm32 => 8,
}

View file

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

View file

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

View file

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

View file

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

View file

@ -21,7 +21,7 @@ impl LlvmAlignment<'_> for IntWidth {
// 128-bit integers are not consistently represented by LLVM.
// - AArch64 uses 16-byte alignment (https://godbolt.org/z/dYrfG5o4b)
// - x86-64 uses 8-byte alignment (https://godbolt.org/z/qj5Mann6b)
let arch = interner.target_info().architecture;
let arch = interner.target().architecture();
match arch {
Architecture::X86_64 => 8,
_ => 16,
@ -33,7 +33,7 @@ impl LlvmAlignment<'_> for IntWidth {
impl<'a> LlvmAlignment<'a> for FloatWidth {
fn llvm_alignment_bytes(&self, interner: &STLayoutInterner<'a>) -> u32 {
self.alignment_bytes(interner.target_info())
self.alignment_bytes(interner.target())
}
}
@ -48,7 +48,7 @@ impl<'a> LlvmAlignment<'a> for Builtin<'a> {
use std::mem::align_of;
use Builtin::*;
let ptr_width = interner.target_info().ptr_width() as u32;
let ptr_width = interner.target().ptr_width() as u32;
// for our data structures, what counts is the alignment of the `( ptr, len )` tuple, and
// since both of those are one pointer size, the alignment of that structure is a pointer
@ -99,7 +99,7 @@ impl<'a> LlvmAlignment<'a> for UnionLayout<'a> {
Recursive(_)
| NullableWrapped { .. }
| NullableUnwrapped { .. }
| NonNullableUnwrapped(_) => interner.target_info().ptr_width() as u32,
| NonNullableUnwrapped(_) => interner.target().ptr_width() as u32,
}
}
}
@ -120,7 +120,7 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> {
.llvm_alignment_bytes(interner),
Builtin(builtin) => builtin.llvm_alignment_bytes(interner),
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) | Erased(_) => {
interner.target_info().ptr_width() as u32
interner.target().ptr_width() as u32
}
}
}

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:?}")
});
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
if env.target.operating_system() == roc_target::OperatingSystem::Windows {
// On windows zig uses a vector type <2xi64> instead of a i128 value
let vec_type = env.context.i64_type().vec_type(2);
if ret.get_type() == vec_type.into() {
@ -70,7 +70,7 @@ fn call_bitcode_fn_help<'ctx>(
let it = args
.iter()
.map(|x| {
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
if env.target.operating_system() == roc_target::OperatingSystem::Windows {
if x.get_type() == env.context.i128_type().into() {
let parent = env
.builder
@ -1067,7 +1067,7 @@ pub(crate) fn call_str_bitcode_fn<'ctx>(
use bumpalo::collections::Vec;
use roc_target::Architecture::*;
match env.target_info.architecture {
match env.target.architecture() {
Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> =
Vec::with_capacity_in(other_arguments.len() + 2 * strings.len(), env.arena);
@ -1123,7 +1123,7 @@ pub(crate) fn call_list_bitcode_fn<'ctx>(
use bumpalo::collections::Vec;
use roc_target::Architecture::*;
match env.target_info.architecture {
match env.target.architecture() {
Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> =
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,
};
use roc_std::RocDec;
use roc_target::{PtrWidth, TargetInfo};
use roc_target::{PtrWidth, Target};
use std::convert::TryInto;
use std::path::Path;
use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple};
use super::convert::{struct_type_from_union_layout, RocUnion};
use super::intrinsics::{
@ -737,7 +736,7 @@ pub struct Env<'a, 'ctx, 'env> {
pub compile_unit: &'env DICompileUnit<'ctx>,
pub module: &'ctx Module<'ctx>,
pub interns: Interns,
pub target_info: TargetInfo,
pub target: Target,
pub mode: LlvmBackendMode,
pub exposed_to_host: MutSet<Symbol>,
}
@ -750,7 +749,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
pub fn ptr_int(&self) -> IntType<'ctx> {
let ctx = self.context;
match self.target_info.ptr_width() {
match self.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => ctx.i32_type(),
roc_target::PtrWidth::Bytes8 => ctx.i64_type(),
}
@ -763,14 +762,14 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
pub fn twice_ptr_int(&self) -> IntType<'ctx> {
let ctx = self.context;
match self.target_info.ptr_width() {
match self.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => ctx.i64_type(),
roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
}
}
pub fn small_str_bytes(&self) -> u32 {
self.target_info.ptr_width() as u32 * 3
self.target.ptr_width() as u32 * 3
}
pub fn build_intrinsic_call(
@ -872,7 +871,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
) -> CallSiteValue<'ctx> {
let false_val = self.context.bool_type().const_int(0, false);
let intrinsic_name = match self.target_info.ptr_width() {
let intrinsic_name = match self.target.ptr_width() {
roc_target::PtrWidth::Bytes8 => LLVM_MEMSET_I64,
roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32,
};
@ -932,7 +931,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
env: &Env<'a, 'ctx, 'env>,
string: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
match env.target_info.ptr_width() {
match env.target.ptr_width() {
PtrWidth::Bytes4 => {
// we need to pass the string by reference, but we currently hold the value.
let alloca = env
@ -1011,48 +1010,29 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
}
pub fn module_from_builtins<'ctx>(
target: &target_lexicon::Triple,
target: Target,
ctx: &'ctx Context,
module_name: &str,
) -> Module<'ctx> {
// In the build script for the builtins module, we compile the builtins into LLVM bitcode
let bitcode_bytes: &[u8] = if target == &target_lexicon::Triple::host() {
let bitcode_bytes: &[u8] = if target == target_lexicon::Triple::host().into() {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-host.bc")
} else {
match target {
Triple {
architecture: Architecture::Wasm32,
..
} => {
Target::Wasm32 => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-wasm32.bc")
}
Triple {
architecture: Architecture::X86_32(_),
operating_system: OperatingSystem::Linux,
..
} => {
Target::LinuxX32 => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86.bc")
}
Triple {
architecture: Architecture::X86_64,
operating_system: OperatingSystem::Linux,
..
} => {
Target::LinuxX64 => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86_64.bc")
}
Triple {
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
operating_system: OperatingSystem::Linux,
..
} => {
Target::LinuxArm64 => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-aarch64.bc")
}
Triple {
architecture: Architecture::X86_64,
operating_system: OperatingSystem::Windows,
..
} => {
Target::WinX64 => {
include_bytes!("../../../builtins/bitcode/zig-out/builtins-windows-x86_64.bc")
}
_ => panic!("The zig builtins are not currently built for this target: {target:?}"),
@ -1416,7 +1396,7 @@ fn build_string_literal<'ctx>(
let alloca = const_str_alloca_ptr(env, parent, ptr, number_of_elements, number_of_elements);
match env.target_info.ptr_width() {
match env.target.ptr_width() {
PtrWidth::Bytes4 => {
env.builder
.new_build_load(zig_str_type(env), alloca, "load_const_str")
@ -1449,7 +1429,7 @@ fn small_str_ptr_width_8<'ctx>(
parent: FunctionValue<'ctx>,
str_literal: &str,
) -> PointerValue<'ctx> {
debug_assert_eq!(env.target_info.ptr_width() as u8, 8);
debug_assert_eq!(env.target.ptr_width() as u8, 8);
let mut array = [0u8; 24];
@ -1473,7 +1453,7 @@ fn small_str_ptr_width_8<'ctx>(
}
fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> {
debug_assert_eq!(env.target_info.ptr_width() as u8, 4);
debug_assert_eq!(env.target.ptr_width() as u8, 4);
let mut array = [0u8; 12];
@ -1779,7 +1759,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(
env,
if union_layout.stores_tag_id_in_pointer(env.target_info) {
if union_layout.stores_tag_id_in_pointer(env.target) {
tag_pointer_clear_tag_id(env, tag_ptr)
} else {
tag_ptr
@ -1876,7 +1856,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(
env,
if union_layout.stores_tag_id_in_pointer(env.target_info) {
if union_layout.stores_tag_id_in_pointer(env.target) {
tag_pointer_clear_tag_id(env, tag_ptr)
} else {
tag_ptr
@ -2261,7 +2241,7 @@ fn build_wrapped_tag<'a, 'ctx>(
);
let struct_type = env.context.struct_type(&field_types, false);
if union_layout.stores_tag_id_as_data(env.target_info) {
if union_layout.stores_tag_id_as_data(env.target) {
let tag_id_ptr = builder.new_build_struct_gep(
union_struct_type,
raw_data_ptr,
@ -2556,7 +2536,7 @@ fn tag_pointer_set_tag_id<'ctx>(
pointer: PointerValue<'ctx>,
) -> PointerValue<'ctx> {
// we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3)
debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32);
debug_assert!((tag_id as u32) < env.target.ptr_width() as u32);
let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false);
@ -2580,8 +2560,8 @@ fn tag_pointer_set_tag_id<'ctx>(
.new_build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr")
}
pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) {
match target_info.ptr_width() {
pub fn tag_pointer_tag_id_bits_and_mask(target: Target) -> (u64, u64) {
match target.ptr_width() {
roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111),
roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011),
}
@ -2591,7 +2571,7 @@ pub fn tag_pointer_read_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
) -> IntValue<'ctx> {
let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target_info);
let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target);
let ptr_int = env.ptr_int();
let as_int = env.builder.new_build_ptr_to_int(pointer, ptr_int, "to_int");
@ -2607,7 +2587,7 @@ pub fn tag_pointer_clear_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
) -> PointerValue<'ctx> {
let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info);
let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target);
let as_int = env
.builder
@ -2725,7 +2705,7 @@ pub fn get_tag_id<'a, 'ctx>(
UnionLayout::Recursive(_) => {
let argument_ptr = argument.into_pointer_value();
if union_layout.stores_tag_id_as_data(env.target_info) {
if union_layout.stores_tag_id_as_data(env.target) {
get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
} else {
tag_pointer_read_tag_id(env, argument_ptr)
@ -2756,7 +2736,7 @@ pub fn get_tag_id<'a, 'ctx>(
{
env.builder.position_at_end(else_block);
let tag_id = if union_layout.stores_tag_id_as_data(env.target_info) {
let tag_id = if union_layout.stores_tag_id_as_data(env.target) {
get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
} else {
tag_pointer_read_tag_id(env, argument_ptr)
@ -2894,7 +2874,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
union_layout: UnionLayout<'a>,
fields: &[&[InLayout<'a>]],
) -> PointerValue<'ctx> {
let ptr_bytes = env.target_info;
let ptr_bytes = env.target;
let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) {
RocUnion::tagged_from_slices(layout_interner, env.context, fields)
@ -2988,11 +2968,11 @@ fn list_literal<'a, 'ctx>(
let size = list_length * element_width as usize;
let alignment = layout_interner
.alignment_bytes(element_layout)
.max(env.target_info.ptr_width() as u32);
.max(env.target.ptr_width() as u32);
let mut is_all_constant = true;
let zero_elements =
(env.target_info.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize;
(env.target.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize;
// runtime-evaluated elements
let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena);
@ -3498,7 +3478,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
if value.is_pointer_value() {
let clear_tag_id = match other_layout {
LayoutRepr::Union(union_layout) => {
union_layout.stores_tag_id_in_pointer(env.target_info)
union_layout.stores_tag_id_in_pointer(env.target)
}
_ => false,
};
@ -3562,7 +3542,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
let value = value.into_pointer_value();
let clear_tag_id = match layout_interner.runtime_representation(layout) {
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target_info),
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target),
_ => false,
};
@ -3640,7 +3620,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
if env.mode.runs_expects() {
bd.position_at_end(throw_block);
match env.target_info.ptr_width() {
match env.target.ptr_width() {
roc_target::PtrWidth::Bytes8 => {
let shared_memory = SharedMemoryPointer::get(env);
@ -3712,7 +3692,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
if env.mode.runs_expects() {
bd.position_at_end(throw_block);
match env.target_info.ptr_width() {
match env.target.ptr_width() {
roc_target::PtrWidth::Bytes8 => {
let shared_memory = SharedMemoryPointer::get(env);
@ -4891,7 +4871,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
// On x86_*, Modify the argument to specify it is passed by value and nonnull
// Aarch*, just passes in the pointer directly.
if matches!(
env.target_info.architecture,
env.target.architecture(),
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
) {
let c_abi_type = match layout_interner.get_repr(*layout) {
@ -5072,7 +5052,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
}
pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
let word_type = match env.target_info.ptr_width() {
let word_type = match env.target.ptr_width() {
PtrWidth::Bytes4 => env.context.i32_type(),
PtrWidth::Bytes8 => env.context.i64_type(),
};
@ -5088,7 +5068,7 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
// The following three words are available for use in a target-specific manner.
//
// So, let's create a 5-word buffer.
let size = if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
let size = if env.target.operating_system() == roc_target::OperatingSystem::Windows {
// Due to https://github.com/llvm/llvm-project/issues/72908
// on windows, we store the register contents into this buffer directly!
30
@ -5114,10 +5094,10 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
let jmp_buf = get_sjlj_buffer(env);
if env.target_info.architecture == roc_target::Architecture::Aarch64 {
if env.target.architecture() == roc_target::Architecture::Aarch64 {
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_SETJMP)
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
} else if env.target.operating_system() == roc_target::OperatingSystem::Windows {
// Due to https://github.com/llvm/llvm-project/issues/72908, we use a setjmp defined as asm in Zig
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_WINDOWS_SETJMP)
} else {
@ -6770,10 +6750,14 @@ pub fn to_cc_return<'a>(
layout: InLayout<'a>,
) -> CCReturn {
let return_size = layout_interner.stack_size(layout);
let pass_result_by_pointer = match env.target_info.operating_system {
roc_target::OperatingSystem::Windows => return_size > env.target_info.ptr_width() as u32,
roc_target::OperatingSystem::Unix => return_size > 2 * env.target_info.ptr_width() as u32,
roc_target::OperatingSystem::Wasi => return_size > 2 * env.target_info.ptr_width() as u32,
// TODO: loop back and update this. It actually cares about the full abi (arch + os)
let pass_result_by_pointer = match env.target.operating_system() {
roc_target::OperatingSystem::Windows => return_size > env.target.ptr_width() as u32,
roc_target::OperatingSystem::Linux
| roc_target::OperatingSystem::Mac
| roc_target::OperatingSystem::Freestanding => {
return_size > 2 * env.target.ptr_width() as u32
}
};
if return_size == 0 {
@ -6996,7 +6980,7 @@ fn define_global_str_literal_ptr<'ctx>(
ptr,
&[env
.ptr_int()
.const_int(env.target_info.ptr_width() as u64, false)],
.const_int(env.target.ptr_width() as u64, false)],
"get_rc_ptr",
)
};
@ -7026,11 +7010,11 @@ fn define_global_str_literal<'ctx>(
Some(current) => current,
None => {
let size = message.bytes().len() + env.target_info.ptr_width() as usize;
let size = message.bytes().len() + env.target.ptr_width() as usize;
let mut bytes = Vec::with_capacity_in(size, env.arena);
// insert NULL bytes for the refcount
for _ in 0..env.target_info.ptr_width() as usize {
for _ in 0..env.target.ptr_width() as usize {
bytes.push(env.context.i8_type().const_zero());
}
@ -7049,7 +7033,7 @@ fn define_global_str_literal<'ctx>(
// strings are NULL-terminated, which means we can't store the refcount (which is 8
// NULL bytes)
global.set_constant(true);
global.set_alignment(env.target_info.ptr_width() as u32);
global.set_alignment(env.target.ptr_width() as u32);
global.set_unnamed_addr(true);
global.set_linkage(inkwell::module::Linkage::Private);

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

View file

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

View file

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

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 => {
// We don't need these functions on Windows
}
@ -266,7 +266,7 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
// write our error message to the RocStr pointer
{
let loaded_roc_str = match env.target_info.ptr_width() {
let loaded_roc_str = match env.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => roc_str_arg,
// On 64-bit we pass RocStrs by reference internally
roc_target::PtrWidth::Bytes8 => {
@ -315,12 +315,12 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
pub fn build_longjmp_call(env: &Env) {
let jmp_buf = get_sjlj_buffer(env);
if env.target_info.architecture == roc_target::Architecture::Aarch64 {
if env.target.architecture() == roc_target::Architecture::Aarch64 {
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
let tag = env.context.i32_type().const_int(1, false);
let _call =
call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP);
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
} else if env.target.operating_system() == roc_target::OperatingSystem::Windows {
let tag = env.context.i32_type().const_int(1, false);
let _call = call_void_bitcode_fn(
env,

View file

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

View file

@ -80,7 +80,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> {
let current = self.get_refcount(env);
let one = match env.target_info.ptr_width() {
let one = match env.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => {
env.context.i32_type().const_int(i32::MIN as u64, false)
}
@ -128,7 +128,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
) {
let alignment = layout
.allocation_alignment_bytes(layout_interner)
.max(env.target_info.ptr_width() as u32);
.max(env.target.ptr_width() as u32);
let context = env.context;
let block = env.builder.get_insert_block().expect("to be in a function");
@ -1034,7 +1034,7 @@ pub fn build_header_help<'ctx>(
// this should be `Linkage::Private`, but that will remove all of the code for the inc/dec
// functions on windows. LLVM just does not emit the assembly for them. Investigate why this is
let linkage = if let roc_target::OperatingSystem::Windows = env.target_info.operating_system {
let linkage = if let roc_target::OperatingSystem::Windows = env.target.operating_system() {
Linkage::External
} else {
Linkage::Private
@ -1162,7 +1162,7 @@ fn build_rec_union_help<'a, 'ctx>(
debug_assert!(arg_val.is_pointer_value());
let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val);
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) {
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target) {
tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
} else {
arg_val.into_pointer_value()

View file

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

View file

@ -18,16 +18,16 @@ use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::ir::{Proc, ProcLayout};
use roc_mono::layout::{LayoutIds, STLayoutInterner};
use roc_target::TargetInfo;
use roc_target::Target;
use roc_wasm_module::parse::ParseError;
use roc_wasm_module::{Align, LocalId, ValueType, WasmModule};
use crate::backend::{ProcLookupData, ProcSource, WasmBackend};
use crate::code_builder::CodeBuilder;
const TARGET_INFO: TargetInfo = TargetInfo::default_wasm32();
const TARGET: Target = Target::Wasm32;
const PTR_SIZE: u32 = {
let value = TARGET_INFO.ptr_width() as u32;
let value = TARGET.ptr_width() as u32;
// const assert that our pointer width is actually 4
// the code relies on the pointer width being exactly 4
@ -135,7 +135,7 @@ pub fn build_app_module<'a, 'r>(
host_to_app_map,
host_module,
fn_index_offset,
CodeGenHelp::new(env.arena, TargetInfo::default_wasm32(), env.module_id),
CodeGenHelp::new(env.arena, Target::Wasm32, env.module_id),
);
if DEBUG_SETTINGS.user_procs_ir {

View file

@ -67,7 +67,8 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
let arena = Bump::new();
let cwd = std::env::current_dir().unwrap();
let source = roc_builtins::roc::module_source(module_id);
let target_info = roc_target::TargetInfo::default_x86_64();
// This is just for typechecking. Target shouldn't matter.
let target = roc_target::Target::LinuxX64;
let function_kind = roc_solve::FunctionKind::LambdaSet;
let res_module = roc_load_internal::file::load_and_typecheck_str(
@ -76,7 +77,7 @@ fn write_types_for_module_real(module_id: ModuleId, filename: &str, output_path:
source,
cwd,
Default::default(),
target_info,
target,
function_kind,
roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE,

View file

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

View file

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

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

View file

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

View file

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

View file

@ -383,7 +383,7 @@ pub fn refcount_reset_proc_body<'a>(
};
// Constant for unique refcount
let refcount_1_encoded = match root.target_info.ptr_width() {
let refcount_1_encoded = match root.target.ptr_width() {
PtrWidth::Bytes4 => i32::MIN as i128,
PtrWidth::Bytes8 => i64::MIN as i128,
}
@ -407,7 +407,7 @@ pub fn refcount_reset_proc_body<'a>(
);
let mask_lower_bits = match layout_interner.get_repr(layout) {
LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info),
LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target),
_ => false,
};
@ -508,7 +508,7 @@ pub fn refcount_resetref_proc_body<'a>(
};
// Constant for unique refcount
let refcount_1_encoded = match root.target_info.ptr_width() {
let refcount_1_encoded = match root.target.ptr_width() {
PtrWidth::Bytes4 => i32::MIN as i128,
PtrWidth::Bytes8 => i64::MIN as i128,
}
@ -532,7 +532,7 @@ pub fn refcount_resetref_proc_body<'a>(
);
let mask_lower_bits = match layout_interner.get_repr(layout) {
LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target_info),
LayoutRepr::Union(ul) => ul.stores_tag_id_in_pointer(root.target),
_ => false,
};
@ -617,7 +617,7 @@ fn rc_ptr_from_data_ptr_help<'a>(
// Pointer size constant
let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size");
let ptr_size_expr = Expr::Literal(Literal::Int(
(root.target_info.ptr_width() as i128).to_ne_bytes(),
(root.target.ptr_width() as i128).to_ne_bytes(),
));
let ptr_size_stmt = |next| Stmt::Let(ptr_size_sym, ptr_size_expr, root.layout_isize, next);
@ -630,7 +630,7 @@ fn rc_ptr_from_data_ptr_help<'a>(
},
arguments: root.arena.alloc([addr_sym, ptr_size_sym]),
});
let sub_stmt = |next| Stmt::Let(rc_addr_sym, sub_expr, Layout::usize(root.target_info), next);
let sub_stmt = |next| Stmt::Let(rc_addr_sym, sub_expr, Layout::usize(root.target), next);
// Typecast the refcount address from integer to pointer
let cast_expr = Expr::Call(Call {
@ -697,7 +697,7 @@ fn modify_refcount<'a>(
}
HelperOp::Dec | HelperOp::DecRef(_) => {
debug_assert!(alignment >= root.target_info.ptr_width() as u32);
debug_assert!(alignment >= root.target.ptr_width() as u32);
let (op, ptr) = match ptr {
Pointer::ToData(s) => (LowLevel::RefCountDecDataPtr, s),
@ -780,7 +780,7 @@ fn refcount_str<'a>(
};
let length_stmt = |next| Stmt::Let(length, length_expr, layout_isize, next);
let alignment = root.target_info.ptr_width() as u32;
let alignment = root.target.ptr_width() as u32;
// let is_slice = lowlevel NumLt length zero
let is_slice = root.create_symbol(ident_ids, "is_slice");
@ -1032,7 +1032,7 @@ fn refcount_list<'a>(
//
let alignment = Ord::max(
root.target_info.ptr_width() as u32,
root.target.ptr_width() as u32,
layout_interner.alignment_bytes(elem_layout),
);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,7 @@ use bumpalo::collections::CollectIn;
use roc_collections::{MutMap, MutSet};
use roc_module::low_level::LowLevel;
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_target::TargetInfo;
use roc_target::Target;
/**
Insert reset and reuse operations into the IR.
@ -30,7 +30,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>(
arena: &'a Bump,
layout_interner: &'i STLayoutInterner<'a>,
home: ModuleId,
target_info: TargetInfo,
target: Target,
ident_ids: &'i mut IdentIds,
update_mode_ids: &'i mut UpdateModeIds,
procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
@ -44,7 +44,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>(
let new_proc = insert_reset_reuse_operations_proc(
arena,
layout_interner,
target_info,
target,
home,
ident_ids,
update_mode_ids,
@ -58,7 +58,7 @@ pub fn insert_reset_reuse_operations<'a, 'i>(
fn insert_reset_reuse_operations_proc<'a, 'i>(
arena: &'a Bump,
layout_interner: &'i STLayoutInterner<'a>,
target_info: TargetInfo,
target: Target,
home: ModuleId,
ident_ids: &'i mut IdentIds,
update_mode_ids: &'i mut UpdateModeIds,
@ -70,7 +70,7 @@ fn insert_reset_reuse_operations_proc<'a, 'i>(
}
let mut env = ReuseEnvironment {
target_info,
target,
symbol_tags: MutMap::default(),
non_unique_symbols: MutSet::default(),
reuse_tokens: MutMap::default(),
@ -464,7 +464,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
),
ModifyRc::Free(_) => {
if union_layout
.stores_tag_id_in_pointer(environment.target_info)
.stores_tag_id_in_pointer(environment.target)
{
(
Symbol::new(home, ident_ids.gen_unique()),
@ -761,7 +761,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
// Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump.
let mut first_pass_body_environment = ReuseEnvironment {
target_info: environment.target_info,
target: environment.target,
symbol_tags: environment.symbol_tags.clone(),
non_unique_symbols: environment.non_unique_symbols.clone(),
reuse_tokens: max_reuse_token_symbols.clone(),
@ -924,7 +924,7 @@ fn insert_reset_reuse_operations_stmt<'a, 'i>(
let (second_pass_body_environment, second_pass_body) = {
// Create a new environment for the body. With everything but the jump reuse tokens. As those should be given by the jump.
let mut body_environment = ReuseEnvironment {
target_info: environment.target_info,
target: environment.target,
symbol_tags: environment.symbol_tags.clone(),
non_unique_symbols: environment.non_unique_symbols.clone(),
reuse_tokens: used_reuse_tokens.clone(),
@ -1182,7 +1182,7 @@ enum JoinPointReuseTokens<'a> {
#[derive(Clone)]
struct ReuseEnvironment<'a> {
target_info: TargetInfo,
target: Target,
symbol_tags: MutMap<Symbol, Tag>,
non_unique_symbols: MutSet<Symbol>,
reuse_tokens: ReuseTokens<'a>,

View file

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

View file

@ -3,70 +3,104 @@
// See github.com/roc-lang/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
use strum_macros::{EnumCount, EnumIter, EnumString, IntoStaticStr};
use std::str::FromStr;
use roc_error_macros::user_error;
use strum_macros::{EnumCount, EnumIter};
use target_lexicon::Triple;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum OperatingSystem {
Freestanding,
Linux,
Mac,
Windows,
Unix,
Wasi,
}
impl OperatingSystem {
pub const fn new(target: target_lexicon::OperatingSystem) -> Option<Self> {
match target {
target_lexicon::OperatingSystem::Windows => Some(OperatingSystem::Windows),
target_lexicon::OperatingSystem::Wasi => Some(OperatingSystem::Wasi),
target_lexicon::OperatingSystem::Linux => Some(OperatingSystem::Unix),
target_lexicon::OperatingSystem::MacOSX { .. } => Some(OperatingSystem::Unix),
target_lexicon::OperatingSystem::Darwin => Some(OperatingSystem::Unix),
target_lexicon::OperatingSystem::Unknown => Some(OperatingSystem::Unix),
_ => None,
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PtrWidth {
Bytes4 = 4,
Bytes8 = 8,
}
pub const fn object_file_ext(&self) -> &str {
match self {
OperatingSystem::Windows => "obj",
OperatingSystem::Unix => "o",
OperatingSystem::Wasi => "wasm",
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter, EnumCount)]
pub enum Architecture {
Aarch32,
Aarch64,
Wasm32,
X86_32,
X86_64,
}
pub const fn static_library_file_ext(&self) -> &str {
match self {
OperatingSystem::Windows => "lib",
OperatingSystem::Unix => "a",
OperatingSystem::Wasi => "wasm",
}
}
pub const fn executable_file_ext(&self) -> Option<&str> {
match self {
OperatingSystem::Windows => Some("exe"),
OperatingSystem::Unix => None,
OperatingSystem::Wasi => Some("wasm"),
}
impl std::fmt::Display for Architecture {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let arch_str = match self {
Architecture::Aarch32 => "aarch32",
Architecture::Aarch64 => "aarch64",
Architecture::Wasm32 => "wasm32",
Architecture::X86_32 => "x86_32",
Architecture::X86_64 => "x86_64",
};
write!(f, "{}", arch_str)
}
}
impl From<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 {
impl Architecture {
pub const fn ptr_width(&self) -> PtrWidth {
self.architecture.ptr_width()
use Architecture::*;
match self {
X86_64 | Aarch64 => PtrWidth::Bytes8,
X86_32 | Aarch32 | Wasm32 => PtrWidth::Bytes4,
}
}
pub const fn ptr_alignment_bytes(&self) -> usize {
self.ptr_width() as usize
}
}
#[derive(Debug, Copy, Clone, EnumIter, PartialEq, Eq)]
pub enum Target {
LinuxX32,
LinuxX64,
LinuxArm64,
MacX64,
MacArm64,
WinX32,
WinX64,
WinArm64,
Wasm32,
}
impl Target {
pub const fn architecture(&self) -> Architecture {
use Target::*;
match self {
LinuxX32 | WinX32 => Architecture::X86_32,
LinuxX64 | WinX64 | MacX64 => Architecture::X86_64,
LinuxArm64 | WinArm64 | MacArm64 => Architecture::Aarch64,
Wasm32 => Architecture::Wasm32,
}
}
pub const fn operating_system(&self) -> OperatingSystem {
use Target::*;
match self {
LinuxX32 | LinuxX64 | LinuxArm64 => OperatingSystem::Linux,
MacX64 | MacArm64 => OperatingSystem::Mac,
WinX32 | WinX64 | WinArm64 => OperatingSystem::Windows,
Wasm32 => OperatingSystem::Freestanding,
}
}
pub const fn arch_os(&self) -> (Architecture, OperatingSystem) {
(self.architecture(), self.operating_system())
}
pub const fn ptr_width(&self) -> PtrWidth {
self.architecture().ptr_width()
}
pub const fn ptr_size(&self) -> usize {
@ -85,196 +119,177 @@ impl TargetInfo {
}
pub const fn ptr_alignment_bytes(&self) -> usize {
self.architecture.ptr_alignment_bytes()
self.architecture().ptr_alignment_bytes()
}
pub const fn default_aarch64() -> Self {
TargetInfo {
architecture: Architecture::Aarch64,
operating_system: OperatingSystem::Unix,
}
}
pub const fn default_x86_64() -> Self {
TargetInfo {
architecture: Architecture::X86_64,
operating_system: OperatingSystem::Unix,
}
}
pub const fn default_wasm32() -> Self {
TargetInfo {
architecture: Architecture::Wasm32,
operating_system: OperatingSystem::Wasi,
}
}
}
impl From<&target_lexicon::Triple> for TargetInfo {
fn from(triple: &target_lexicon::Triple) -> Self {
let architecture = Architecture::from(triple.architecture);
let operating_system = OperatingSystem::from(triple.operating_system);
Self {
architecture,
operating_system,
}
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PtrWidth {
Bytes4 = 4,
Bytes8 = 8,
}
/// These should be sorted alphabetically!
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, EnumIter, EnumCount)]
#[repr(u8)]
pub enum Architecture {
Aarch32,
Aarch64,
Wasm32,
X86_32,
X86_64,
}
impl Architecture {
pub const fn ptr_width(&self) -> PtrWidth {
use Architecture::*;
pub const fn object_file_ext(&self) -> &str {
use Target::*;
match self {
X86_64 | Aarch64 => PtrWidth::Bytes8,
X86_32 | Aarch32 | Wasm32 => PtrWidth::Bytes4,
LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "o",
WinX32 | WinX64 | WinArm64 => "obj",
Wasm32 => "wasm",
}
}
pub const fn ptr_alignment_bytes(&self) -> usize {
self.ptr_width() as usize
}
}
impl From<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::*;
pub const fn static_library_file_ext(&self) -> &str {
use Target::*;
match self {
Target::System => Triple::host(),
Target::LinuxX32 => Triple {
architecture: Architecture::X86_32(X86_32Architecture::I386),
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Linux,
environment: Environment::Unknown,
binary_format: BinaryFormat::Elf,
},
Target::LinuxX64 => Triple {
architecture: Architecture::X86_64,
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Linux,
environment: Environment::Unknown,
binary_format: BinaryFormat::Elf,
},
Target::LinuxArm64 => Triple {
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Linux,
environment: Environment::Unknown,
binary_format: BinaryFormat::Elf,
},
Target::WinX32 => Triple {
architecture: Architecture::X86_32(X86_32Architecture::I386),
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Windows,
environment: Environment::Gnu,
binary_format: BinaryFormat::Coff,
},
Target::WinX64 => Triple {
architecture: Architecture::X86_64,
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Windows,
environment: Environment::Gnu,
binary_format: BinaryFormat::Coff,
},
Target::WinArm64 => Triple {
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Windows,
environment: Environment::Gnu,
binary_format: BinaryFormat::Coff,
},
Target::MacX64 => Triple {
architecture: Architecture::X86_64,
vendor: Vendor::Apple,
operating_system: MACOS,
environment: Environment::Unknown,
binary_format: BinaryFormat::Macho,
},
Target::MacArm64 => Triple {
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
vendor: Vendor::Apple,
operating_system: MACOS,
environment: Environment::Unknown,
binary_format: BinaryFormat::Macho,
},
Target::Wasm32 => Triple {
architecture: Architecture::Wasm32,
vendor: Vendor::Unknown,
operating_system: OperatingSystem::Wasi,
environment: Environment::Unknown,
binary_format: BinaryFormat::Wasm,
},
LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => "a",
WinX32 | WinX64 | WinArm64 => "lib",
Wasm32 => "wasm",
}
}
pub const fn executable_file_ext(&self) -> Option<&str> {
use Target::*;
match self {
LinuxX32 | LinuxX64 | LinuxArm64 | MacX64 | MacArm64 => None,
WinX32 | WinX64 | WinArm64 => Some("exe"),
Wasm32 => Some("wasm"),
}
}
}
impl From<&Target> for Triple {
pub enum ParseError {
InvalidTargetString,
}
impl FromStr for Target {
type Err = ParseError;
fn from_str(s: &str) -> Result<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 {
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))
}
}
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 (builtin_module, source, path) = module_source_and_path(builtin);
let target_info = roc_target::TargetInfo::default_x86_64();
let target = roc_target::Target::LinuxX64;
let LoadedModule {
mut interns,
@ -531,7 +531,7 @@ where
source,
path.parent().unwrap().to_path_buf(),
Default::default(),
target_info,
target,
FunctionKind::LambdaSet,
roc_reporting::report::RenderTarget::ColorTerminal,
roc_reporting::report::DEFAULT_PALETTE,

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
use bumpalo::Bump;
use roc_gen_wasm::Env;
use roc_target::TargetInfo;
use roc_target::Target;
use std::fs;
use std::process::Command;
@ -259,7 +259,7 @@ fn test_help(
dump_filename: &str,
) {
let arena = Bump::new();
let mut layout_interner = STLayoutInterner::with_capacity(4, TargetInfo::default_wasm32());
let mut layout_interner = STLayoutInterner::with_capacity(4, Target::Wasm32);
let BackendInputs {
env,

View file

@ -27,7 +27,7 @@ use roc_mono::ir::ProcLayout;
use roc_mono::layout::STLayoutInterner;
use test_mono_macros::*;
const TARGET_INFO: roc_target::TargetInfo = roc_target::TargetInfo::default_x86_64();
const TARGET: roc_target::Target = roc_target::Target::LinuxX64;
/// Without this, some tests pass in `cargo test --release` but fail without
/// the --release flag because they run out of stack space. This increases
@ -104,7 +104,7 @@ fn compiles_to_ir(test_name: &str, src: &str, mode: &str, allow_type_errors: boo
}
let load_config = LoadConfig {
target_info: TARGET_INFO,
target: TARGET,
// TODO parameterize
function_kind: FunctionKind::LambdaSet,
threading: Threading::Single,

View file

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

View file

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

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 {
let arena = Bump::new();
let load_config = LoadConfig {
target_info: roc_target::TargetInfo::default_x86_64(), // This is just type-checking for docs, so "target" doesn't matter
target: roc_target::Target::LinuxX64, // This is just type-checking for docs, so "target" doesn't matter
function_kind: roc_solve::FunctionKind::LambdaSet,
render: roc_reporting::report::RenderTarget::ColorTerminal,
palette: roc_reporting::report::DEFAULT_PALETTE,

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

@ -332,8 +332,7 @@ impl<'a> Surgeries<'a> {
}
/// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_elf(
endianness: target_lexicon::Endianness,
pub(crate) fn preprocess_elf_le(
host_exe_path: &Path,
metadata_path: &Path,
preprocessed_path: &Path,
@ -479,11 +478,6 @@ pub(crate) fn preprocess_elf(
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 ElfDynamicDeps {
@ -496,12 +490,11 @@ pub(crate) fn preprocess_elf(
&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
gen_elf_le(
let out_mmap = gen_elf_le(
exec_data,
&mut md,
preprocessed_path,
@ -511,15 +504,7 @@ pub(crate) fn preprocess_elf(
dynamic_lib_count,
shared_lib_index,
verbose,
)
}
target_lexicon::Endianness::Big => {
// TODO probably need to make gen_elf a macro to get this
// to work, which is annoying. A parameterized function
// does *not* work.
todo!("Roc does not yet support big-endian ELF hosts!");
}
};
);
let platform_gen_duration = platform_gen_start.elapsed();
@ -1743,7 +1728,7 @@ mod tests {
use crate::preprocessed_host_filename;
use indoc::indoc;
use target_lexicon::Triple;
use roc_target::Target;
const ELF64_DYNHOST: &[u8] = include_bytes!("../dynhost_benchmarks_elf64") as &[_];
@ -1778,9 +1763,6 @@ mod tests {
fn collect_undefined_symbols_elf() {
let object = object::File::parse(ELF64_DYNHOST).unwrap();
let mut triple = Triple::host();
triple.binary_format = target_lexicon::BinaryFormat::Elf;
let mut keys: Vec<_> = object
.dynamic_symbols()
.filter(is_roc_undefined)
@ -1800,7 +1782,7 @@ mod tests {
}
#[allow(dead_code)]
fn zig_host_app_help(dir: &Path, target: &Triple) {
fn zig_host_app_help(dir: &Path, target: Target) {
let host_zig = indoc!(
r#"
const std = @import("std");
@ -1885,10 +1867,9 @@ mod tests {
panic!("zig build-exe failed");
}
let preprocessed_host_filename = dir.join(preprocessed_host_filename(target).unwrap());
let preprocessed_host_filename = dir.join(preprocessed_host_filename(target));
preprocess_elf(
target_lexicon::Endianness::Little,
preprocess_elf_le(
&dir.join("host"),
&dir.join("metadata"),
&preprocessed_host_filename,
@ -1911,12 +1892,10 @@ mod tests {
#[cfg(target_os = "linux")]
#[test]
fn zig_host_app() {
use std::str::FromStr;
let dir = tempfile::tempdir().unwrap();
let dir = dir.path();
zig_host_app_help(dir, &Triple::from_str("x86_64-unknown-linux-musl").unwrap());
zig_host_app_help(dir, Target::LinuxX64);
let output = std::process::Command::new(dir.join("final"))
.current_dir(dir)

View file

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

View file

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

View file

@ -11,11 +11,10 @@ use roc_module::symbol::Interns;
use roc_packaging::cache::RocCacheDir;
use roc_reporting::report::{RenderTarget, DEFAULT_PALETTE};
use roc_solve::FunctionKind;
use roc_target::get_target_triple_str;
use roc_target::{Architecture, OperatingSystem, Target};
use std::cmp::Ordering;
use std::mem;
use std::path::{Path, PathBuf};
use target_lexicon::Triple;
mod elf;
mod macho;
@ -31,30 +30,13 @@ pub enum LinkType {
None = 2,
}
pub fn supported(link_type: LinkType, target: &Triple) -> bool {
pub fn supported(link_type: LinkType, target: Target) -> bool {
if let LinkType::Executable = link_type {
match target {
Triple {
architecture: target_lexicon::Architecture::X86_64,
operating_system: target_lexicon::OperatingSystem::Linux,
binary_format: target_lexicon::BinaryFormat::Elf,
..
} => true,
Target::LinuxX64 => true,
Target::WinX64 => true,
// macho support is incomplete
Triple {
operating_system: target_lexicon::OperatingSystem::Darwin,
binary_format: target_lexicon::BinaryFormat::Macho,
..
} => false,
Triple {
architecture: target_lexicon::Architecture::X86_64,
operating_system: target_lexicon::OperatingSystem::Windows,
binary_format: target_lexicon::BinaryFormat::Coff,
..
} => true,
Target::MacX64 => false,
_ => false,
}
} else {
@ -64,18 +46,16 @@ pub fn supported(link_type: LinkType, target: &Triple) -> bool {
pub const PRECOMPILED_HOST_EXT: &str = "rh"; // Short for "roc host"
pub fn preprocessed_host_filename(target: &Triple) -> Option<String> {
roc_target::get_target_triple_str(target).map(|x| format!("{x}.{PRECOMPILED_HOST_EXT}"))
pub fn preprocessed_host_filename(target: Target) -> String {
format!("{target}.{PRECOMPILED_HOST_EXT}")
}
fn metadata_file_name(target: &Triple) -> String {
let target_triple_str = get_target_triple_str(target);
format!("metadata_{}.rm", target_triple_str.unwrap_or("unknown"))
fn metadata_file_name(target: Target) -> String {
format!("metadata_{}.rm", target)
}
pub fn link_preprocessed_host(
target: &Triple,
target: Target,
platform_path: &Path,
roc_app_bytes: &[u8],
binary_path: &Path,
@ -88,21 +68,20 @@ pub fn link_preprocessed_host(
pub fn generate_stub_lib(
input_path: &Path,
roc_cache_dir: RocCacheDir<'_>,
triple: &Triple,
target: Target,
function_kind: FunctionKind,
) -> (PathBuf, PathBuf, Vec<String>) {
// Note: this should theoretically just be able to load the host, I think.
// Instead, I am loading an entire app because that was simpler and had example code.
// If this was expected to stay around for the the long term, we should change it.
// But hopefully it will be removable once we have surgical linking on all platforms.
let target_info = triple.into();
let arena = &bumpalo::Bump::new();
let loaded = roc_load::load_and_monomorphize(
arena,
input_path.to_path_buf(),
roc_cache_dir,
LoadConfig {
target_info,
target,
function_kind,
render: RenderTarget::Generic,
palette: DEFAULT_PALETTE,
@ -138,14 +117,14 @@ pub fn generate_stub_lib(
};
if let EntryPoint::Executable { platform_path, .. } = &loaded.entry_point {
let stub_lib = if let target_lexicon::OperatingSystem::Windows = triple.operating_system {
let stub_lib = if target.operating_system() == OperatingSystem::Windows {
platform_path.with_file_name("libapp.obj")
} else {
platform_path.with_file_name("libapp.so")
};
let stub_dll_symbols = exposed_symbols.stub_dll_symbols();
generate_dynamic_lib(triple, &stub_dll_symbols, &stub_lib);
generate_dynamic_lib(target, &stub_dll_symbols, &stub_lib);
(platform_path.into(), stub_lib, stub_dll_symbols)
} else {
unreachable!();
@ -153,11 +132,11 @@ pub fn generate_stub_lib(
}
pub fn generate_stub_lib_from_loaded(
target: &Triple,
target: Target,
platform_main_roc: &Path,
stub_dll_symbols: &[String],
) -> PathBuf {
let stub_lib_path = if let target_lexicon::OperatingSystem::Windows = target.operating_system {
let stub_lib_path = if target.operating_system() == OperatingSystem::Windows {
platform_main_roc.with_file_name("libapp.dll")
} else {
platform_main_roc.with_file_name("libapp.so")
@ -252,7 +231,7 @@ impl ExposedSymbols {
}
}
fn generate_dynamic_lib(target: &Triple, stub_dll_symbols: &[String], stub_lib_path: &Path) {
fn generate_dynamic_lib(target: Target, stub_dll_symbols: &[String], stub_lib_path: &Path) {
if !stub_lib_is_up_to_date(target, stub_lib_path, stub_dll_symbols) {
let bytes = crate::generate_dylib::generate(target, stub_dll_symbols)
.unwrap_or_else(|e| internal_error!("{e}"));
@ -261,7 +240,7 @@ fn generate_dynamic_lib(target: &Triple, stub_dll_symbols: &[String], stub_lib_p
internal_error!("failed to write stub lib to {:?}: {e}", stub_lib_path)
}
if let target_lexicon::OperatingSystem::Windows = target.operating_system {
if target.operating_system() == OperatingSystem::Windows {
generate_import_library(stub_lib_path, stub_dll_symbols);
}
}
@ -336,24 +315,22 @@ fn generate_def_file(custom_names: &[String]) -> Result<String, std::fmt::Error>
Ok(def_file)
}
fn object_matches_target<'a>(target: &Triple, object: &object::File<'a, &'a [u8]>) -> bool {
use target_lexicon::{Architecture as TLA, OperatingSystem as TLO};
match target.architecture {
TLA::X86_64 => {
fn object_matches_target<'a>(target: Target, object: &object::File<'a, &'a [u8]>) -> bool {
match target.architecture() {
Architecture::X86_64 => {
if object.architecture() != object::Architecture::X86_64 {
return false;
}
let target_format = match target.operating_system {
TLO::Linux => object::BinaryFormat::Elf,
TLO::Windows => object::BinaryFormat::Pe,
let target_format = match target.operating_system() {
OperatingSystem::Linux => object::BinaryFormat::Elf,
OperatingSystem::Windows => object::BinaryFormat::Pe,
_ => todo!("surgical linker does not support target {:?}", target),
};
object.format() == target_format
}
TLA::Aarch64(_) => object.architecture() == object::Architecture::Aarch64,
Architecture::Aarch64 => object.architecture() == object::Architecture::Aarch64,
_ => todo!("surgical linker does not support target {:?}", target),
}
}
@ -361,7 +338,7 @@ fn object_matches_target<'a>(target: &Triple, object: &object::File<'a, &'a [u8]
/// Checks whether the stub `.dll/.so` is up to date, in other words that it exports exactly the
/// symbols that it is supposed to export, and is built for the right target. If this is the case,
/// we can skip rebuildingthe stub lib.
fn stub_lib_is_up_to_date(target: &Triple, stub_lib_path: &Path, custom_names: &[String]) -> bool {
fn stub_lib_is_up_to_date(target: Target, stub_lib_path: &Path, custom_names: &[String]) -> bool {
if !std::path::Path::exists(stub_lib_path) {
return false;
}
@ -386,14 +363,14 @@ fn stub_lib_is_up_to_date(target: &Triple, stub_lib_path: &Path, custom_names: &
}
pub fn preprocess_host(
target: &Triple,
target: Target,
platform_main_roc: &Path,
preprocessed_path: &Path,
shared_lib: &Path,
stub_dll_symbols: &[String],
) {
let metadata_path = platform_main_roc.with_file_name(metadata_file_name(target));
let host_exe_path = if let target_lexicon::OperatingSystem::Windows = target.operating_system {
let host_exe_path = if target.operating_system() == OperatingSystem::Windows {
platform_main_roc.with_file_name("dynhost.exe")
} else {
platform_main_roc.with_file_name("dynhost")
@ -414,7 +391,7 @@ pub fn preprocess_host(
/// Constructs a `Metadata` from a host executable binary, and writes it to disk
#[allow(clippy::too_many_arguments)]
fn preprocess(
target: &Triple,
target: Target,
host_exe_path: &Path,
metadata_path: &Path,
preprocessed_path: &Path,
@ -427,14 +404,9 @@ fn preprocess(
println!("Targeting: {target}");
}
let endianness = target
.endianness()
.unwrap_or(target_lexicon::Endianness::Little);
match target.binary_format {
target_lexicon::BinaryFormat::Elf => {
crate::elf::preprocess_elf(
endianness,
match target.arch_os() {
(_, OperatingSystem::Linux) => {
crate::elf::preprocess_elf_le(
host_exe_path,
metadata_path,
preprocessed_path,
@ -444,9 +416,8 @@ fn preprocess(
);
}
target_lexicon::BinaryFormat::Macho => {
crate::macho::preprocess_macho(
target,
(_, OperatingSystem::Mac) => {
crate::macho::preprocess_macho_le(
host_exe_path,
metadata_path,
preprocessed_path,
@ -456,7 +427,7 @@ fn preprocess(
);
}
target_lexicon::BinaryFormat::Coff => {
(_, OperatingSystem::Windows) => {
crate::pe::preprocess_windows(
host_exe_path,
metadata_path,
@ -468,12 +439,9 @@ fn preprocess(
.unwrap_or_else(|e| internal_error!("{}", e));
}
target_lexicon::BinaryFormat::Wasm => {
(Architecture::Wasm32, _) => {
todo!("Roc does not yet support web assembly hosts!");
}
target_lexicon::BinaryFormat::Unknown => {
internal_error!("Roc does not support unknown host binary formats!");
}
other => {
internal_error!(
concat!(
@ -492,14 +460,14 @@ fn surgery(
executable_path: &Path,
verbose: bool,
time: bool,
target: &Triple,
target: Target,
) {
match target.binary_format {
target_lexicon::BinaryFormat::Elf => {
match target.arch_os() {
(_, OperatingSystem::Linux) => {
crate::elf::surgery_elf(roc_app_bytes, metadata_path, executable_path, verbose, time);
}
target_lexicon::BinaryFormat::Macho => {
(_, OperatingSystem::Mac) => {
crate::macho::surgery_macho(
roc_app_bytes,
metadata_path,
@ -509,16 +477,13 @@ fn surgery(
);
}
target_lexicon::BinaryFormat::Coff => {
(_, OperatingSystem::Windows) => {
crate::pe::surgery_pe(executable_path, metadata_path, roc_app_bytes);
}
target_lexicon::BinaryFormat::Wasm => {
(Architecture::Wasm32, _) => {
todo!("Roc does not yet support web assembly hosts!");
}
target_lexicon::BinaryFormat::Unknown => {
internal_error!("Roc does not support unknown host binary formats!");
}
other => {
internal_error!(
concat!(

View file

@ -17,7 +17,6 @@ use std::{
path::Path,
time::{Duration, Instant},
};
use target_lexicon::Triple;
use crate::{
align_by_constraint, align_to_offset_by_constraint, load_struct_inplace,
@ -322,8 +321,7 @@ impl<'a> Surgeries<'a> {
}
/// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_macho(
target: &Triple,
pub(crate) fn preprocess_macho_le(
host_exe_path: &Path,
metadata_path: &Path,
preprocessed_path: &Path,
@ -544,15 +542,6 @@ pub(crate) fn preprocess_macho(
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 ElfDynamicDeps {
@ -564,9 +553,9 @@ pub(crate) fn preprocess_macho(
// &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 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?
md.load_align_constraint = 4096;
gen_macho_le(
let out_mmap = gen_macho_le(
exec_data,
&mut md,
preprocessed_path,
macho_load_so_offset,
target,
verbose,
)
}
target_lexicon::Endianness::Big => {
// TODO Is big-endian macOS even a thing that exists anymore?
// Just ancient PowerPC machines maybe?
todo!("Roc does not yet support big-endian macOS hosts!");
}
}
};
);
let platform_gen_duration = platform_gen_start.elapsed();
@ -652,7 +632,6 @@ fn gen_macho_le(
md: &mut Metadata,
out_filename: &Path,
macho_load_so_offset: usize,
_target: &Triple,
_verbose: bool,
) -> MmapMut {
// Just adding some extra context/useful info here.

View file

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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