Compare commits
4 Commits
50703e515d
...
d5fb0ddfd9
Author | SHA1 | Date |
---|---|---|
David Mak | d5fb0ddfd9 | |
David Mak | 14b9869cd1 | |
David Mak | 1e6a4e4f59 | |
David Mak | 04e0e4c66b |
|
@ -8,7 +8,7 @@ use std::sync::Arc;
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
memory_buffer::MemoryBuffer,
|
memory_buffer::MemoryBuffer,
|
||||||
module::{Linkage, Module},
|
module::{Linkage, Module},
|
||||||
passes::{PassManager, PassManagerBuilder},
|
passes::PassBuilderOptions,
|
||||||
targets::*,
|
targets::*,
|
||||||
OptimizationLevel,
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
|
@ -654,12 +654,16 @@ impl Nac3 {
|
||||||
global_option = global.get_next_global();
|
global_option = global.get_next_global();
|
||||||
}
|
}
|
||||||
|
|
||||||
let builder = PassManagerBuilder::create();
|
let target_machine = self.llvm_options.target
|
||||||
builder.set_optimization_level(OptimizationLevel::Aggressive);
|
.create_target_machine(self.llvm_options.opt_level)
|
||||||
let passes = PassManager::create(());
|
.expect("couldn't create target machine");
|
||||||
builder.set_inliner_with_threshold(255);
|
|
||||||
builder.populate_module_pass_manager(&passes);
|
let pass_options = PassBuilderOptions::create();
|
||||||
passes.run_on(&main);
|
pass_options.set_merge_functions(true);
|
||||||
|
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||||
|
if let Err(err) = result {
|
||||||
|
panic!("Failed to run optimization for module `main`\n{}", err.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
link_fn(&main)
|
link_fn(&main)
|
||||||
}
|
}
|
||||||
|
@ -673,6 +677,15 @@ impl Nac3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [String] representing the target CPU used for compiling to [isa].
|
||||||
|
fn get_llvm_target_cpu(isa: Isa) -> String {
|
||||||
|
match isa {
|
||||||
|
Isa::Host => TargetMachine::get_host_cpu_name().to_string(),
|
||||||
|
Isa::RiscV32G | Isa::RiscV32IMA => "generic-rv32".to_string(),
|
||||||
|
Isa::CortexA9 => "cortex-a9".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the [String] representing the target features used for compiling to [isa].
|
/// Returns the [String] representing the target features used for compiling to [isa].
|
||||||
fn get_llvm_target_features(isa: Isa) -> String {
|
fn get_llvm_target_features(isa: Isa) -> String {
|
||||||
match isa {
|
match isa {
|
||||||
|
@ -688,7 +701,7 @@ impl Nac3 {
|
||||||
fn get_llvm_target_options(isa: Isa) -> CodeGenTargetMachineOptions {
|
fn get_llvm_target_options(isa: Isa) -> CodeGenTargetMachineOptions {
|
||||||
CodeGenTargetMachineOptions {
|
CodeGenTargetMachineOptions {
|
||||||
triple: Nac3::get_llvm_target_triple(isa).as_str().to_string_lossy().into_owned(),
|
triple: Nac3::get_llvm_target_triple(isa).as_str().to_string_lossy().into_owned(),
|
||||||
cpu: String::default(),
|
cpu: Nac3::get_llvm_target_cpu(isa),
|
||||||
features: Nac3::get_llvm_target_features(isa),
|
features: Nac3::get_llvm_target_features(isa),
|
||||||
reloc_mode: RelocMode::PIC,
|
reloc_mode: RelocMode::PIC,
|
||||||
..CodeGenTargetMachineOptions::from_host()
|
..CodeGenTargetMachineOptions::from_host()
|
||||||
|
|
|
@ -15,7 +15,7 @@ use inkwell::{
|
||||||
builder::Builder,
|
builder::Builder,
|
||||||
context::Context,
|
context::Context,
|
||||||
module::Module,
|
module::Module,
|
||||||
passes::{PassManager, PassManagerBuilder},
|
passes::PassBuilderOptions,
|
||||||
targets::{CodeModel, RelocMode, Target, TargetMachine, TargetTriple},
|
targets::{CodeModel, RelocMode, Target, TargetMachine, TargetTriple},
|
||||||
types::{AnyType, BasicType, BasicTypeEnum},
|
types::{AnyType, BasicType, BasicTypeEnum},
|
||||||
values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue},
|
values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue},
|
||||||
|
@ -32,7 +32,6 @@ use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
};
|
};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
|
|
||||||
pub mod concrete_type;
|
pub mod concrete_type;
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
|
@ -54,12 +53,6 @@ pub struct StaticValueStore {
|
||||||
|
|
||||||
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
||||||
|
|
||||||
lazy_static!(
|
|
||||||
// HACK: The Mutex is a work-around for issue
|
|
||||||
// https://git.m-labs.hk/M-Labs/nac3/issues/275
|
|
||||||
static ref PASSES_INIT_LOCK: Mutex<AtomicBool> = Mutex::new(AtomicBool::new(true));
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Additional options for LLVM during codegen.
|
/// Additional options for LLVM during codegen.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct CodeGenLLVMOptions {
|
pub struct CodeGenLLVMOptions {
|
||||||
|
@ -305,23 +298,11 @@ impl WorkerRegistry {
|
||||||
context.i32_type().const_int(4, false),
|
context.i32_type().const_int(4, false),
|
||||||
);
|
);
|
||||||
|
|
||||||
let passes = PassManager::create(&module);
|
|
||||||
|
|
||||||
// HACK: This critical section is a work-around for issue
|
|
||||||
// https://git.m-labs.hk/M-Labs/nac3/issues/275
|
|
||||||
{
|
|
||||||
let _data = PASSES_INIT_LOCK.lock();
|
|
||||||
let pass_builder = PassManagerBuilder::create();
|
|
||||||
pass_builder.set_optimization_level(self.llvm_options.opt_level);
|
|
||||||
pass_builder.populate_function_pass_manager(&passes);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut errors = HashSet::new();
|
let mut errors = HashSet::new();
|
||||||
while let Some(task) = self.receiver.recv().unwrap() {
|
while let Some(task) = self.receiver.recv().unwrap() {
|
||||||
match gen_func(&context, generator, self, builder, module, task) {
|
match gen_func(&context, generator, self, builder, module, task) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
builder = result.0;
|
builder = result.0;
|
||||||
passes.run_on(&result.2);
|
|
||||||
module = result.1;
|
module = result.1;
|
||||||
}
|
}
|
||||||
Err((old_builder, e)) => {
|
Err((old_builder, e)) => {
|
||||||
|
@ -345,9 +326,21 @@ impl WorkerRegistry {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pass_options = PassBuilderOptions::create();
|
||||||
|
let target_machine = self.llvm_options.target.create_target_machine(
|
||||||
|
self.llvm_options.opt_level
|
||||||
|
).expect(format!("could not create target machine from properties {:?}", self.llvm_options.target).as_str());
|
||||||
|
let passes = format!("default<O{}>", self.llvm_options.opt_level as u32);
|
||||||
|
|
||||||
|
let result = module.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||||
|
if let Err(err) = result {
|
||||||
|
panic!("Failed to run optimization for module `{}`\n{}",
|
||||||
|
module.get_name().to_str().unwrap(),
|
||||||
|
err.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
if self.llvm_options.emit_llvm {
|
if self.llvm_options.emit_llvm {
|
||||||
println!("LLVM IR for {}", module.get_name().to_str().unwrap());
|
println!("LLVM IR for {}\n{}", module.get_name().to_str().unwrap(), module.to_string());
|
||||||
println!("{}", module.to_string());
|
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ count=0
|
||||||
for demo in src/*.py; do
|
for demo in src/*.py; do
|
||||||
echo -n "checking $demo... "
|
echo -n "checking $demo... "
|
||||||
./interpret_demo.py $demo > interpreted.log
|
./interpret_demo.py $demo > interpreted.log
|
||||||
./run_demo.sh $demo > run.log
|
./run_demo.sh "$@" $demo > run.log
|
||||||
diff -Nau interpreted.log run.log
|
diff -Nau interpreted.log run.log
|
||||||
echo "ok"
|
echo "ok"
|
||||||
let "count+=1"
|
let "count+=1"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
memory_buffer::MemoryBuffer,
|
memory_buffer::MemoryBuffer,
|
||||||
passes::{PassManager, PassManagerBuilder},
|
passes::PassBuilderOptions,
|
||||||
targets::*,
|
targets::*,
|
||||||
OptimizationLevel,
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,18 @@ struct CommandLineArgs {
|
||||||
/// Whether to emit LLVM IR at the end of every module.
|
/// Whether to emit LLVM IR at the end of every module.
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
emit_llvm: bool,
|
emit_llvm: bool,
|
||||||
|
|
||||||
|
/// The target triple to compile for.
|
||||||
|
#[arg(long)]
|
||||||
|
triple: Option<String>,
|
||||||
|
|
||||||
|
/// The target CPU to compile for.
|
||||||
|
#[arg(long)]
|
||||||
|
mcpu: Option<String>,
|
||||||
|
|
||||||
|
/// Additional target features to enable/disable, specified using the `+`/`-` prefixes.
|
||||||
|
#[arg(long)]
|
||||||
|
target_features: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_typevar_definition(
|
fn handle_typevar_definition(
|
||||||
|
@ -177,7 +189,24 @@ fn handle_assignment_pattern(
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli = CommandLineArgs::parse();
|
let cli = CommandLineArgs::parse();
|
||||||
let CommandLineArgs { file_name, threads, opt_level, emit_llvm } = cli;
|
let CommandLineArgs {
|
||||||
|
file_name,
|
||||||
|
threads,
|
||||||
|
opt_level,
|
||||||
|
emit_llvm,
|
||||||
|
triple,
|
||||||
|
mcpu,
|
||||||
|
target_features,
|
||||||
|
} = cli;
|
||||||
|
|
||||||
|
Target::initialize_all(&InitializationConfig::default());
|
||||||
|
|
||||||
|
let host_target_machine = CodeGenTargetMachineOptions::from_host();
|
||||||
|
let triple = triple.unwrap_or(host_target_machine.triple.clone());
|
||||||
|
let mcpu = mcpu
|
||||||
|
.map(|arg| if arg == "native" { host_target_machine.cpu.clone() } else { arg })
|
||||||
|
.unwrap_or_default();
|
||||||
|
let target_features = target_features.unwrap_or_default();
|
||||||
let opt_level = match opt_level {
|
let opt_level = match opt_level {
|
||||||
0 => OptimizationLevel::None,
|
0 => OptimizationLevel::None,
|
||||||
1 => OptimizationLevel::Less,
|
1 => OptimizationLevel::Less,
|
||||||
|
@ -186,8 +215,6 @@ fn main() {
|
||||||
_ => OptimizationLevel::Aggressive,
|
_ => OptimizationLevel::Aggressive,
|
||||||
};
|
};
|
||||||
|
|
||||||
Target::initialize_all(&InitializationConfig::default());
|
|
||||||
|
|
||||||
let program = match fs::read_to_string(file_name.clone()) {
|
let program = match fs::read_to_string(file_name.clone()) {
|
||||||
Ok(program) => program,
|
Ok(program) => program,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -272,7 +299,12 @@ fn main() {
|
||||||
|
|
||||||
let llvm_options = CodeGenLLVMOptions {
|
let llvm_options = CodeGenLLVMOptions {
|
||||||
opt_level,
|
opt_level,
|
||||||
target: CodeGenTargetMachineOptions::from_host_triple(),
|
target: CodeGenTargetMachineOptions {
|
||||||
|
triple,
|
||||||
|
cpu: mcpu,
|
||||||
|
features: target_features,
|
||||||
|
..host_target_machine
|
||||||
|
},
|
||||||
emit_llvm,
|
emit_llvm,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -325,16 +357,17 @@ fn main() {
|
||||||
function_iter = func.get_next_function();
|
function_iter = func.get_next_function();
|
||||||
}
|
}
|
||||||
|
|
||||||
let builder = PassManagerBuilder::create();
|
|
||||||
builder.set_optimization_level(OptimizationLevel::Aggressive);
|
|
||||||
let passes = PassManager::create(());
|
|
||||||
builder.set_inliner_with_threshold(255);
|
|
||||||
builder.populate_module_pass_manager(&passes);
|
|
||||||
passes.run_on(&main);
|
|
||||||
|
|
||||||
let target_machine = llvm_options.target
|
let target_machine = llvm_options.target
|
||||||
.create_target_machine(llvm_options.opt_level)
|
.create_target_machine(llvm_options.opt_level)
|
||||||
.expect("couldn't create target machine");
|
.expect("couldn't create target machine");
|
||||||
|
|
||||||
|
let pass_options = PassBuilderOptions::create();
|
||||||
|
pass_options.set_merge_functions(true);
|
||||||
|
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||||
|
if let Err(err) = result {
|
||||||
|
panic!("Failed to run optimization for module `main`\n{}", err.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
target_machine
|
target_machine
|
||||||
.write_to_file(&main, FileType::Object, Path::new("module.o"))
|
.write_to_file(&main, FileType::Object, Path::new("module.o"))
|
||||||
.expect("couldn't write module to file");
|
.expect("couldn't write module to file");
|
||||||
|
|
Loading…
Reference in New Issue