mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Extract target triple and linking logic
This commit is contained in:
parent
a108544fa8
commit
26dfa01205
7 changed files with 282 additions and 203 deletions
|
@ -10,4 +10,6 @@
|
|||
// and encouraging shortcuts here creates bad incentives. I would rather temporarily
|
||||
// re-enable this when working on performance optimizations than have it block PRs.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
pub mod link;
|
||||
pub mod program;
|
||||
pub mod target;
|
||||
|
|
66
compiler/build/src/link.rs
Normal file
66
compiler/build/src/link.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use crate::target::arch_str;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::{Child, Command};
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
|
||||
pub fn link(
|
||||
target: &Triple,
|
||||
binary_path: &Path,
|
||||
host_input_path: &Path,
|
||||
dest_filename: &Path,
|
||||
) -> io::Result<Child> {
|
||||
match target {
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => link_linux(
|
||||
arch_str(target),
|
||||
binary_path,
|
||||
host_input_path,
|
||||
dest_filename,
|
||||
),
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => todo!("link macos"),
|
||||
_ => panic!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
}
|
||||
}
|
||||
|
||||
fn link_linux(
|
||||
arch: &str,
|
||||
binary_path: &Path,
|
||||
host_input_path: &Path,
|
||||
dest_filename: &Path,
|
||||
) -> io::Result<Child> {
|
||||
Command::new("ld")
|
||||
.args(&[
|
||||
"-arch",
|
||||
arch,
|
||||
"/usr/lib/x86_64-linux-gnu/crti.o",
|
||||
"/usr/lib/x86_64-linux-gnu/crtn.o",
|
||||
"/usr/lib/x86_64-linux-gnu/Scrt1.o",
|
||||
"-dynamic-linker",
|
||||
"/lib64/ld-linux-x86-64.so.2",
|
||||
// Libraries - see https://github.com/rtfeldman/roc/pull/554#discussion_r496365925
|
||||
// for discussion and further references
|
||||
"-lc",
|
||||
"-lm",
|
||||
"-lpthread",
|
||||
"-ldl",
|
||||
"-lrt",
|
||||
"-lutil",
|
||||
"-lc_nonshared",
|
||||
// "-lc++", // TODO shouldn't we need this?
|
||||
// "-lgcc", // TODO will eventually need compiler_rt from gcc or something - see https://github.com/rtfeldman/roc/pull/554#discussion_r496370840
|
||||
// "-lunwind", // TODO will eventually need this, see https://github.com/rtfeldman/roc/pull/554#discussion_r496370840
|
||||
"-o",
|
||||
binary_path.to_str().unwrap(), // app
|
||||
host_input_path.to_str().unwrap(), // host.o
|
||||
dest_filename.to_str().unwrap(), // roc_app.o
|
||||
])
|
||||
.spawn()
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
use crate::target;
|
||||
use bumpalo::Bump;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::targets::{
|
||||
CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetTriple,
|
||||
};
|
||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||
use inkwell::OptimizationLevel;
|
||||
use roc_collections::all::default_hasher;
|
||||
use roc_gen::layout_id::LayoutIds;
|
||||
|
@ -12,7 +11,7 @@ use roc_mono::ir::{Env, PartialProc, Procs};
|
|||
use roc_mono::layout::{Layout, LayoutCache};
|
||||
use std::collections::HashSet;
|
||||
use std::path::{Path, PathBuf};
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
use target_lexicon::Triple;
|
||||
|
||||
// TODO how should imported modules factor into this? What if those use builtins too?
|
||||
// TODO this should probably use more helper functions
|
||||
|
@ -295,66 +294,10 @@ pub fn gen(
|
|||
|
||||
// Emit the .o file
|
||||
|
||||
// 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.
|
||||
let arch_str = match target.architecture {
|
||||
Architecture::X86_64 => {
|
||||
Target::initialize_x86(&InitializationConfig::default());
|
||||
|
||||
"x86-64"
|
||||
}
|
||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => {
|
||||
// NOTE: why not enable arm and wasm by default?
|
||||
//
|
||||
// We had some trouble getting them to link properly. This may be resolved in the
|
||||
// future, or maybe it was just some weird configuration on one machine.
|
||||
Target::initialize_arm(&InitializationConfig::default());
|
||||
|
||||
"arm"
|
||||
}
|
||||
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => {
|
||||
Target::initialize_webassembly(&InitializationConfig::default());
|
||||
|
||||
"wasm32"
|
||||
}
|
||||
_ => panic!(
|
||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||
target.architecture
|
||||
),
|
||||
};
|
||||
|
||||
let opt = OptimizationLevel::Aggressive;
|
||||
let reloc = RelocMode::Default;
|
||||
let model = CodeModel::Default;
|
||||
|
||||
// Best guide I've found on how to determine these magic strings:
|
||||
//
|
||||
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
|
||||
let target_triple_str = match target {
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => "x86_64-unknown-linux-gnu",
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "x86_64-unknown-darwin10",
|
||||
_ => panic!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
};
|
||||
let target_machine = Target::from_name(arch_str)
|
||||
.unwrap()
|
||||
.create_target_machine(
|
||||
&TargetTriple::create(target_triple_str),
|
||||
arch_str,
|
||||
"+avx2", // TODO this string was used uncritically from an example, and should be reexamined
|
||||
opt,
|
||||
reloc,
|
||||
model,
|
||||
)
|
||||
.unwrap();
|
||||
let target_machine = target::target_machine(&target, opt, reloc, model).unwrap();
|
||||
|
||||
target_machine
|
||||
.write_to_file(&env.module, FileType::Object, &dest_filename)
|
||||
|
|
76
compiler/build/src/target.rs
Normal file
76
compiler/build/src/target.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use inkwell::targets::{
|
||||
CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple,
|
||||
};
|
||||
use inkwell::OptimizationLevel;
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
|
||||
pub fn target_triple_str(target: &Triple) -> &'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_64,
|
||||
operating_system: OperatingSystem::Darwin,
|
||||
..
|
||||
} => "x86_64-unknown-darwin10",
|
||||
_ => panic!("TODO gracefully handle unsupported target: {:?}", target),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
// 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 => {
|
||||
Target::initialize_x86(&InitializationConfig::default());
|
||||
|
||||
"x86-64"
|
||||
}
|
||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => {
|
||||
// NOTE: why not enable arm and wasm by default?
|
||||
//
|
||||
// We had some trouble getting them to link properly. This may be resolved in the
|
||||
// future, or maybe it was just some weird configuration on one machine.
|
||||
Target::initialize_arm(&InitializationConfig::default());
|
||||
|
||||
"arm"
|
||||
}
|
||||
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => {
|
||||
Target::initialize_webassembly(&InitializationConfig::default());
|
||||
|
||||
"wasm32"
|
||||
}
|
||||
_ => panic!(
|
||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||
target.architecture
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_machine(
|
||||
target: &Triple,
|
||||
opt: OptimizationLevel,
|
||||
reloc: RelocMode,
|
||||
model: CodeModel,
|
||||
) -> Option<TargetMachine> {
|
||||
let arch = arch_str(target);
|
||||
|
||||
Target::from_name(arch).unwrap().create_target_machine(
|
||||
&TargetTriple::create(target_triple_str(target)),
|
||||
arch,
|
||||
"+avx2", // TODO this string was used uncritically from an example, and should be reexamined
|
||||
opt,
|
||||
reloc,
|
||||
model,
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue