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

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",
"",