From 3993a5cf3f25a69fb5116978ddb19cfc978feb28 Mon Sep 17 00:00:00 2001 From: David Mak Date: Wed, 6 Sep 2023 17:50:17 +0800 Subject: [PATCH] core: Add LLVM options to WorkerRegistry --- nac3artiq/src/lib.rs | 19 +++++++++++++++---- nac3core/src/codegen/mod.rs | 17 ++++++++++++++--- nac3core/src/codegen/test.rs | 29 +++++++++++++++++++++++++---- nac3standalone/src/main.rs | 10 +++++++--- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index 049fdeb81..7df32aa6c 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -12,7 +12,7 @@ use inkwell::{ targets::*, OptimizationLevel, }; -use nac3core::codegen::gen_func_impl; +use nac3core::codegen::{CodeGenLLVMOptions, gen_func_impl}; use nac3core::toplevel::builtins::get_exn_constructor; use nac3core::typecheck::typedef::{TypeEnum, Unifier}; use nac3parser::{ @@ -97,7 +97,9 @@ struct Nac3 { top_levels: Vec, string_store: Arc>>, exception_ids: Arc>>, - deferred_eval_store: DeferredEvaluationStore + deferred_eval_store: DeferredEvaluationStore, + /// LLVM-related options for code generation. + llvm_options: CodeGenLLVMOptions, } create_exception!(nac3artiq, CompileError, exceptions::PyException); @@ -588,7 +590,12 @@ impl Nac3 { let membuffer = membuffers.clone(); py.allow_threads(|| { - let (registry, handles) = WorkerRegistry::create_workers(threads, top_level.clone(), f); + let (registry, handles) = WorkerRegistry::create_workers( + threads, + top_level.clone(), + &self.llvm_options, + f + ); registry.add_task(task); registry.wait_tasks_complete(handles); @@ -681,7 +688,7 @@ impl Nac3 { &triple, "", &features, - OptimizationLevel::Default, + self.llvm_options.opt_level, RelocMode::PIC, CodeModel::Default, ) @@ -885,6 +892,10 @@ impl Nac3 { string_store: Default::default(), exception_ids: Default::default(), deferred_eval_store: DeferredEvaluationStore::new(), + llvm_options: CodeGenLLVMOptions { + opt_level: OptimizationLevel::Default, + emit_llvm: false, + } }) } diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index e68f909f3..0bb6c9079 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -132,12 +132,15 @@ pub struct WorkerRegistry { wait_condvar: Condvar, top_level_ctx: Arc, static_value_store: Arc>, + /// LLVM-related options for code generation. + llvm_options: CodeGenLLVMOptions, } impl WorkerRegistry { pub fn create_workers( generators: Vec>, top_level_ctx: Arc, + llvm_options: &CodeGenLLVMOptions, f: Arc, ) -> (Arc, Vec>) { let (sender, receiver) = unbounded(); @@ -158,6 +161,7 @@ impl WorkerRegistry { task_count, wait_condvar, top_level_ctx, + llvm_options: llvm_options.clone(), }); let mut handles = Vec::new(); @@ -242,7 +246,7 @@ impl WorkerRegistry { { let _data = PASSES_INIT_LOCK.lock(); let pass_builder = PassManagerBuilder::create(); - pass_builder.set_optimization_level(OptimizationLevel::Default); + pass_builder.set_optimization_level(self.llvm_options.opt_level); pass_builder.populate_function_pass_manager(&passes); } @@ -274,6 +278,13 @@ impl WorkerRegistry { println!("{}", err.to_string()); panic!() } + + if self.llvm_options.emit_llvm { + println!("LLVM IR for {}", module.get_name().to_str().unwrap()); + println!("{}", module.to_string()); + println!(); + } + f.run(&module); let mut lock = self.task_count.lock(); *lock += 1; @@ -634,7 +645,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte ), /* directory */ "", /* producer */ "NAC3", - /* is_optimized */ true, + /* is_optimized */ registry.llvm_options.opt_level != OptimizationLevel::None, /* compiler command line flags */ "", /* runtime_ver */ 0, /* split_name */ "", @@ -669,7 +680,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte /* is_definition */ true, /* scope_line */ row as u32, /* flags */ inkwell::debug_info::DIFlags::PUBLIC, - /* is_optimized */ true, + /* is_optimized */ registry.llvm_options.opt_level != OptimizationLevel::None, ); fn_val.set_subprogram(func_scope); diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs index 97498d133..32b2abf11 100644 --- a/nac3core/src/codegen/test.rs +++ b/nac3core/src/codegen/test.rs @@ -1,7 +1,7 @@ use crate::{ codegen::{ - concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenTask, DefaultCodeGenerator, - WithCall, WorkerRegistry, + concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenLLVMOptions, CodeGenTask, + DefaultCodeGenerator, WithCall, WorkerRegistry, }, symbol_resolver::{SymbolResolver, ValueEnum}, toplevel::{ @@ -13,6 +13,7 @@ use crate::{ }, }; use indoc::indoc; +use inkwell::OptimizationLevel; use nac3parser::{ ast::{fold::Fold, StrRef}, parser::parse_program, @@ -220,7 +221,17 @@ fn test_primitives() { .trim(); assert_eq!(expected, module.print_to_string().to_str().unwrap().trim()); }))); - let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f); + + let llvm_options = CodeGenLLVMOptions { + opt_level: OptimizationLevel::Default, + emit_llvm: false, + }; + let (registry, handles) = WorkerRegistry::create_workers( + threads, + top_level, + &llvm_options, + f + ); registry.add_task(task); registry.wait_tasks_complete(handles); } @@ -395,7 +406,17 @@ fn test_simple_call() { .trim(); assert_eq!(expected, module.print_to_string().to_str().unwrap().trim()); }))); - let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f); + + let llvm_options = CodeGenLLVMOptions { + opt_level: OptimizationLevel::Default, + emit_llvm: false, + }; + let (registry, handles) = WorkerRegistry::create_workers( + threads, + top_level, + &llvm_options, + f + ); registry.add_task(task); registry.wait_tasks_complete(handles); } diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index 0faedc856..d08baf3d7 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -10,8 +10,8 @@ use std::{borrow::Borrow, collections::HashMap, fs, path::Path, sync::Arc}; use nac3core::{ codegen::{ - concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenTask, DefaultCodeGenerator, - WithCall, WorkerRegistry, + concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenLLVMOptions, CodeGenTask, + DefaultCodeGenerator, WithCall, WorkerRegistry, }, symbol_resolver::SymbolResolver, toplevel::{ @@ -255,6 +255,10 @@ fn main() { } }; + let llvm_options = CodeGenLLVMOptions { + opt_level: OptimizationLevel::Default, + emit_llvm: false, + }; let task = CodeGenTask { subst: Default::default(), symbol_name: "run".to_string(), @@ -278,7 +282,7 @@ fn main() { let threads = (0..threads) .map(|i| Box::new(DefaultCodeGenerator::new(format!("module{}", i), 64))) .collect(); - let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f); + let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, &llvm_options, f); registry.add_task(task); registry.wait_tasks_complete(handles);