mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Split out an optional "llvm" feature
Also move OptLevel out of roc_gen (which should really be called gen_llvm) and into roc_mono, so it's no longer coupled to LLVM.
This commit is contained in:
parent
0e5619c422
commit
b05342c678
14 changed files with 143 additions and 76 deletions
|
@ -1,16 +1,14 @@
|
|||
use crate::target;
|
||||
use crate::target::arch_str;
|
||||
use inkwell::module::Module;
|
||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||
#[cfg(feature = "llvm")]
|
||||
use libloading::{Error, Library};
|
||||
use roc_gen::llvm::build::OptLevel;
|
||||
#[cfg(feature = "llvm")]
|
||||
use roc_mono::ir::OptLevel;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Output};
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum LinkType {
|
||||
|
@ -360,6 +358,9 @@ fn link_linux(
|
|||
};
|
||||
|
||||
let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
init_arch(target);
|
||||
|
||||
// NOTE: order of arguments to `ld` matters here!
|
||||
// The `-l` flags should go after the `.o` arguments
|
||||
Ok((
|
||||
|
@ -477,12 +478,16 @@ fn link_macos(
|
|||
))
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
pub fn module_to_dylib(
|
||||
module: &Module,
|
||||
module: &inkwell::module::Module,
|
||||
target: &Triple,
|
||||
opt_level: OptLevel,
|
||||
) -> Result<Library, Error> {
|
||||
let dir = tempdir().unwrap();
|
||||
use crate::target::{self, convert_opt_level};
|
||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let filename = PathBuf::from("Test.roc");
|
||||
let file_path = dir.path().join(filename);
|
||||
let mut app_o_file = file_path;
|
||||
|
@ -492,7 +497,8 @@ pub fn module_to_dylib(
|
|||
// Emit the .o file using position-indepedent code (PIC) - needed for dylibs
|
||||
let reloc = RelocMode::PIC;
|
||||
let model = CodeModel::Default;
|
||||
let target_machine = target::target_machine(target, opt_level.into(), reloc, model).unwrap();
|
||||
let target_machine =
|
||||
target::target_machine(target, convert_opt_level(opt_level), reloc, model).unwrap();
|
||||
|
||||
target_machine
|
||||
.write_to_file(module, FileType::Object, &app_o_file)
|
||||
|
@ -529,3 +535,13 @@ fn validate_output(file_name: &str, cmd_name: &str, output: Output) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
fn init_arch(target: &Triple) {
|
||||
crate::target::init_arch(target);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "llvm"))]
|
||||
fn init_arch(_target: &Triple) {
|
||||
panic!("Tried to initialize LLVM when crate was not built with `feature = \"llvm\"` enabled");
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use crate::target;
|
||||
use bumpalo::Bump;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||
#[cfg(feature = "llvm")]
|
||||
use roc_gen::llvm::build::module_from_builtins;
|
||||
#[cfg(feature = "llvm")]
|
||||
pub use roc_gen::llvm::build::FunctionIterator;
|
||||
use roc_gen::llvm::build::{module_from_builtins, OptLevel};
|
||||
#[cfg(feature = "llvm")]
|
||||
use roc_load::file::MonomorphizedModule;
|
||||
#[cfg(feature = "llvm")]
|
||||
use roc_mono::ir::OptLevel;
|
||||
#[cfg(feature = "llvm")]
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{Duration, SystemTime};
|
||||
use target_lexicon::Triple;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct CodeGenTiming {
|
||||
|
@ -18,16 +19,24 @@ pub struct CodeGenTiming {
|
|||
// TODO how should imported modules factor into this? What if those use builtins too?
|
||||
// TODO this should probably use more helper functions
|
||||
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
|
||||
#[cfg(feature = "llvm")]
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn gen_from_mono_module(
|
||||
arena: &Bump,
|
||||
arena: &bumpalo::Bump,
|
||||
mut loaded: MonomorphizedModule,
|
||||
roc_file_path: &Path,
|
||||
target: Triple,
|
||||
target: target_lexicon::Triple,
|
||||
app_o_file: &Path,
|
||||
opt_level: OptLevel,
|
||||
emit_debug_info: bool,
|
||||
) -> CodeGenTiming {
|
||||
use crate::target::{self, convert_opt_level};
|
||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||
use inkwell::context::Context;
|
||||
use inkwell::module::Linkage;
|
||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||
use std::time::SystemTime;
|
||||
|
||||
use roc_reporting::report::{
|
||||
can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE,
|
||||
};
|
||||
|
@ -87,9 +96,6 @@ pub fn gen_from_mono_module(
|
|||
// module.strip_debug_info();
|
||||
|
||||
// mark our zig-defined builtins as internal
|
||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||
use inkwell::module::Linkage;
|
||||
|
||||
let app_ll_file = {
|
||||
let mut temp = PathBuf::from(roc_file_path);
|
||||
temp.set_extension("ll");
|
||||
|
@ -226,7 +232,7 @@ pub fn gen_from_mono_module(
|
|||
let reloc = RelocMode::Default;
|
||||
let model = CodeModel::Default;
|
||||
let target_machine =
|
||||
target::target_machine(&target, opt_level.into(), reloc, model).unwrap();
|
||||
target::target_machine(&target, convert_opt_level(opt_level), reloc, model).unwrap();
|
||||
|
||||
target_machine
|
||||
.write_to_file(&env.module, FileType::Object, &app_o_file)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use inkwell::targets::{
|
||||
CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple,
|
||||
#[cfg(feature = "llvm")]
|
||||
use inkwell::{
|
||||
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple},
|
||||
OptimizationLevel,
|
||||
};
|
||||
use inkwell::OptimizationLevel;
|
||||
#[cfg(feature = "llvm")]
|
||||
use roc_mono::ir::OptLevel;
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
|
||||
pub fn target_triple_str(target: &Triple) -> &'static str {
|
||||
|
@ -28,36 +31,20 @@ pub fn target_triple_str(target: &Triple) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
#[cfg(feature = "llvm")]
|
||||
pub fn init_arch(target: &Triple) {
|
||||
match target.architecture {
|
||||
Architecture::X86_64 => {
|
||||
Target::initialize_x86(&InitializationConfig::default());
|
||||
|
||||
"x86-64"
|
||||
}
|
||||
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => {
|
||||
Target::initialize_aarch64(&InitializationConfig::default());
|
||||
"aarch64"
|
||||
}
|
||||
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: {:?}",
|
||||
|
@ -66,6 +53,26 @@ pub fn arch_str(target: &Triple) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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 => "x86-64",
|
||||
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => "aarch64",
|
||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => "arm",
|
||||
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32",
|
||||
_ => panic!(
|
||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||
target.architecture
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
pub fn target_machine(
|
||||
target: &Triple,
|
||||
opt: OptimizationLevel,
|
||||
|
@ -83,3 +90,11 @@ pub fn target_machine(
|
|||
model,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "llvm")]
|
||||
pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel {
|
||||
match level {
|
||||
OptLevel::Normal => OptimizationLevel::None,
|
||||
OptLevel::Optimize => OptimizationLevel::Aggressive,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue