forked from M-Labs/nac3
1
0
Fork 0

core: Add CodeGenTargetMachineOptions

Needed in a future commit.
This commit is contained in:
David Mak 2023-09-11 10:25:44 +08:00 committed by David Mak
parent eb63f2ad48
commit 2482a1ef9b
2 changed files with 99 additions and 29 deletions

View File

@ -12,7 +12,7 @@ use inkwell::{
targets::*, targets::*,
OptimizationLevel, OptimizationLevel,
}; };
use nac3core::codegen::{CodeGenLLVMOptions, gen_func_impl}; use nac3core::codegen::{CodeGenLLVMOptions, CodeGenTargetMachineOptions, gen_func_impl};
use nac3core::toplevel::builtins::get_exn_constructor; use nac3core::toplevel::builtins::get_exn_constructor;
use nac3core::typecheck::typedef::{TypeEnum, Unifier}; use nac3core::typecheck::typedef::{TypeEnum, Unifier};
use nac3parser::{ use nac3parser::{
@ -664,34 +664,42 @@ impl Nac3 {
link_fn(&main) link_fn(&main)
} }
fn get_llvm_target_machine( /// Returns the [TargetTriple] used for compiling to [isa].
&self, fn get_llvm_target_triple(isa: Isa) -> TargetTriple {
) -> TargetMachine { match isa {
let (triple, features) = match self.isa { Isa::Host => TargetMachine::get_default_triple(),
Isa::Host => ( Isa::RiscV32G | Isa::RiscV32IMA => TargetTriple::create("riscv32-unknown-linux"),
TargetMachine::get_default_triple(), Isa::CortexA9 => TargetTriple::create("armv7-unknown-linux-gnueabihf"),
TargetMachine::get_host_cpu_features().to_string(), }
), }
Isa::RiscV32G => {
(TargetTriple::create("riscv32-unknown-linux"), "+a,+m,+f,+d".to_string()) /// Returns the [String] representing the target features used for compiling to [isa].
} fn get_llvm_target_features(isa: Isa) -> String {
Isa::RiscV32IMA => (TargetTriple::create("riscv32-unknown-linux"), "+a,+m".to_string()), match isa {
Isa::CortexA9 => ( Isa::Host => TargetMachine::get_host_cpu_features().to_string(),
TargetTriple::create("armv7-unknown-linux-gnueabihf"), Isa::RiscV32G => "+a,+m,+f,+d".to_string(),
"+dsp,+fp16,+neon,+vfp3,+long-calls".to_string(), Isa::RiscV32IMA => "+a,+m".to_string(),
), Isa::CortexA9 => "+dsp,+fp16,+neon,+vfp3,+long-calls".to_string(),
}; }
let target = }
Target::from_triple(&triple).expect("couldn't create target from target triple");
target /// Returns an instance of [CodeGenTargetMachineOptions] representing the target machine
.create_target_machine( /// options used for compiling to [isa].
&triple, fn get_llvm_target_options(isa: Isa) -> CodeGenTargetMachineOptions {
"", CodeGenTargetMachineOptions {
&features, triple: Nac3::get_llvm_target_triple(isa).as_str().to_string_lossy().into_owned(),
self.llvm_options.opt_level, cpu: String::default(),
RelocMode::PIC, features: Nac3::get_llvm_target_features(isa),
CodeModel::Default, reloc_mode: RelocMode::PIC,
) ..CodeGenTargetMachineOptions::from_host()
}
}
/// Returns an instance of [TargetMachine] used in compiling and linking of a program to the
/// target [isa].
fn get_llvm_target_machine(&self) -> TargetMachine {
Nac3::get_llvm_target_options(self.isa)
.create_target_machine(self.llvm_options.opt_level)
.expect("couldn't create target machine") .expect("couldn't create target machine")
} }
} }

View File

@ -16,6 +16,7 @@ use inkwell::{
context::Context, context::Context,
module::Module, module::Module,
passes::{PassManager, PassManagerBuilder}, passes::{PassManager, PassManagerBuilder},
targets::{CodeModel, RelocMode, Target, TargetMachine, TargetTriple},
types::{AnyType, BasicType, BasicTypeEnum}, types::{AnyType, BasicType, BasicTypeEnum},
values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue}, values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue},
debug_info::{ debug_info::{
@ -68,6 +69,67 @@ pub struct CodeGenLLVMOptions {
pub emit_llvm: bool, pub emit_llvm: bool,
} }
/// Additional options for code generation for the target machine.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CodeGenTargetMachineOptions {
/// The target machine triple.
pub triple: String,
/// The target machine CPU.
pub cpu: String,
/// Additional target machine features.
pub features: String,
/// Relocation mode for code generation.
pub reloc_mode: RelocMode,
/// Code model for code generation.
pub code_model: CodeModel,
}
impl CodeGenTargetMachineOptions {
/// Creates an instance of [CodeGenTargetMachineOptions] using the triple of the host machine.
/// Other options are set to defaults.
pub fn from_host_triple() -> CodeGenTargetMachineOptions {
CodeGenTargetMachineOptions {
triple: TargetMachine::get_default_triple().as_str().to_string_lossy().into_owned(),
cpu: String::default(),
features: String::default(),
reloc_mode: RelocMode::Default,
code_model: CodeModel::Default,
}
}
/// Creates an instance of [CodeGenTargetMachineOptions] using the properties of the host
/// machine. Other options are set to defaults.
pub fn from_host() -> CodeGenTargetMachineOptions {
CodeGenTargetMachineOptions {
cpu: TargetMachine::get_host_cpu_name().to_string(),
features: TargetMachine::get_host_cpu_features().to_string(),
..CodeGenTargetMachineOptions::from_host_triple()
}
}
/// Creates a [TargetMachine] using the target options specified by this struct.
///
/// See [Target::create_target_machine].
pub fn create_target_machine(
&self,
level: OptimizationLevel,
) -> Option<TargetMachine> {
let triple = TargetTriple::create(self.triple.as_str());
let target = Target::from_triple(&triple)
.expect(format!("could not create target from target triple {}", self.triple).as_str());
target.create_target_machine(
&triple,
self.cpu.as_str(),
self.features.as_str(),
level,
self.reloc_mode,
self.code_model
)
}
}
pub struct CodeGenContext<'ctx, 'a> { pub struct CodeGenContext<'ctx, 'a> {
pub ctx: &'ctx Context, pub ctx: &'ctx Context,
pub builder: Builder<'ctx>, pub builder: Builder<'ctx>,