2024-06-12 15:13:09 +08:00
#![ deny(
future_incompatible ,
let_underscore ,
nonstandard_style ,
rust_2024_compatibility ,
clippy ::all
) ]
2024-06-12 12:27:35 +08:00
#![ warn(clippy::pedantic) ]
2024-06-12 15:13:09 +08:00
#![ allow(clippy::too_many_lines, clippy::wildcard_imports) ]
2024-06-12 12:27:35 +08:00
2024-10-03 12:37:56 +08:00
use std ::{
collections ::{ HashMap , HashSet } ,
fs ,
num ::NonZeroUsize ,
path ::Path ,
sync ::Arc ,
2021-10-16 22:17:36 +08:00
} ;
2024-10-03 12:37:56 +08:00
use clap ::Parser ;
use parking_lot ::{ Mutex , RwLock } ;
2021-08-19 15:30:52 +08:00
use nac3core ::{
2021-10-17 13:02:18 +08:00
codegen ::{
2023-09-11 13:12:46 +08:00
concrete_type ::ConcreteTypeStore , irrt ::load_irrt , CodeGenLLVMOptions ,
CodeGenTargetMachineOptions , CodeGenTask , DefaultCodeGenerator , WithCall , WorkerRegistry ,
2021-10-17 13:02:18 +08:00
} ,
2024-10-03 12:37:56 +08:00
inkwell ::{
memory_buffer ::MemoryBuffer , module ::Linkage , passes ::PassBuilderOptions ,
support ::is_multithreaded , targets ::* , OptimizationLevel ,
} ,
nac3parser ::{
ast ::{ Constant , Expr , ExprKind , StmtKind , StrRef } ,
parser ,
} ,
2021-08-25 15:30:36 +08:00
symbol_resolver ::SymbolResolver ,
2021-12-01 22:44:53 +08:00
toplevel ::{
2024-03-04 23:38:52 +08:00
composer ::{ ComposerConfig , TopLevelComposer } ,
2024-06-12 14:45:03 +08:00
helper ::parse_parameter_default_value ,
2024-03-04 23:38:52 +08:00
type_annotation ::* ,
2022-02-21 18:27:46 +08:00
TopLevelDef ,
2021-12-01 22:44:53 +08:00
} ,
2022-02-21 18:27:46 +08:00
typecheck ::{
type_inferencer ::PrimitiveStore ,
2024-03-04 23:38:52 +08:00
typedef ::{ FunSignature , Type , Unifier , VarMap } ,
2022-02-21 18:27:46 +08:00
} ,
} ;
2020-12-17 22:20:30 +08:00
2021-09-19 16:19:16 +08:00
use basic_symbol_resolver ::* ;
2020-12-17 22:20:30 +08:00
2024-10-17 15:57:33 +08:00
mod basic_symbol_resolver ;
2023-09-06 16:34:08 +08:00
/// Command-line argument parser definition.
#[ derive(Parser) ]
#[ command(author, version, about, long_about = None) ]
struct CommandLineArgs {
/// The name of the input file.
file_name : String ,
2023-10-13 14:57:09 +08:00
/// The number of threads allocated to processing the source file. If 0 is passed to this
/// parameter, all available threads will be used for compilation.
2023-10-13 11:22:29 +08:00
#[ arg(short = 'T', default_value_t = 1) ]
2023-09-06 16:34:08 +08:00
threads : u32 ,
2023-09-06 18:49:58 +08:00
/// The level to optimize the LLVM IR.
#[ arg(short = 'O', default_value_t = 2, value_parser = clap::value_parser!(u32).range(0..=3)) ]
opt_level : u32 ,
/// Whether to emit LLVM IR at the end of every module.
2023-10-13 15:00:39 +08:00
///
/// If multithreaded compilation is also enabled, each thread will emit its own module.
2023-09-06 18:49:58 +08:00
#[ arg(long, default_value_t = false) ]
emit_llvm : bool ,
2023-09-12 14:41:34 +08:00
/// 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 > ,
2023-09-06 16:34:08 +08:00
}
2022-04-18 16:02:48 +08:00
fn handle_typevar_definition (
var : & Expr ,
resolver : & ( dyn SymbolResolver + Send + Sync ) ,
def_list : & [ Arc < RwLock < TopLevelDef > > ] ,
unifier : & mut Unifier ,
primitives : & PrimitiveStore ,
2023-11-15 17:30:26 +08:00
) -> Result < Type , HashSet < String > > {
2023-11-28 17:37:49 +08:00
let ExprKind ::Call { func , args , .. } = & var . node else {
2024-06-12 14:45:03 +08:00
return Err ( HashSet ::from ( [ format! (
" expression {var:?} cannot be handled as a generic parameter in global scope "
) ] ) ) ;
2023-11-28 17:37:49 +08:00
} ;
match & func . node {
ExprKind ::Name { id , .. } if id = = & " TypeVar " . into ( ) = > {
2023-12-05 14:37:08 +08:00
let ExprKind ::Constant { value : Constant ::Str ( ty_name ) , .. } = & args [ 0 ] . node else {
2024-06-12 14:45:03 +08:00
return Err ( HashSet ::from ( [ format! (
" Expected string constant for first parameter of `TypeVar`, got {:?} " ,
& args [ 0 ] . node
) ] ) ) ;
2023-12-05 14:37:08 +08:00
} ;
let generic_name : StrRef = ty_name . to_string ( ) . into ( ) ;
2022-04-18 16:02:48 +08:00
let constraints = args
. iter ( )
. skip ( 1 )
2023-11-15 17:30:26 +08:00
. map ( | x | -> Result < Type , HashSet < String > > {
2022-04-18 16:02:48 +08:00
let ty = parse_ast_to_type_annotation_kinds (
resolver ,
def_list ,
unifier ,
primitives ,
x ,
2024-06-12 15:13:09 +08:00
HashMap ::new ( ) ,
2022-04-18 16:02:48 +08:00
) ? ;
2024-07-18 15:47:40 +08:00
get_type_from_type_annotation_kinds (
def_list , unifier , primitives , & ty , & mut None ,
)
2022-04-18 16:02:48 +08:00
} )
. collect ::< Result < Vec < _ > , _ > > ( ) ? ;
2023-12-05 14:37:08 +08:00
let loc = func . location ;
if constraints . len ( ) = = 1 {
2024-06-12 14:45:03 +08:00
return Err ( HashSet ::from ( [ format! (
" A single constraint is not allowed (at {loc}) "
) ] ) ) ;
2023-12-05 14:37:08 +08:00
}
2024-06-13 13:28:39 +08:00
Ok ( unifier . get_fresh_var_with_range ( & constraints , Some ( generic_name ) , Some ( loc ) ) . ty )
2023-12-05 14:37:08 +08:00
}
ExprKind ::Name { id , .. } if id = = & " ConstGeneric " . into ( ) = > {
if args . len ( ) ! = 2 {
2024-06-12 14:45:03 +08:00
return Err ( HashSet ::from ( [ format! (
" Expected 2 arguments for `ConstGeneric`, got {} " ,
args . len ( )
) ] ) ) ;
2023-12-05 14:37:08 +08:00
}
let ExprKind ::Constant { value : Constant ::Str ( ty_name ) , .. } = & args [ 0 ] . node else {
2024-06-12 14:45:03 +08:00
return Err ( HashSet ::from ( [ format! (
" Expected string constant for first parameter of `ConstGeneric`, got {:?} " ,
& args [ 0 ] . node
) ] ) ) ;
2023-12-05 14:37:08 +08:00
} ;
let generic_name : StrRef = ty_name . to_string ( ) . into ( ) ;
let ty = parse_ast_to_type_annotation_kinds (
resolver ,
def_list ,
unifier ,
primitives ,
& args [ 1 ] ,
2024-06-12 15:13:09 +08:00
HashMap ::new ( ) ,
2023-12-05 14:37:08 +08:00
) ? ;
2024-06-12 14:45:03 +08:00
let constraint =
2024-07-18 15:47:40 +08:00
get_type_from_type_annotation_kinds ( def_list , unifier , primitives , & ty , & mut None ) ? ;
2023-12-05 14:37:08 +08:00
let loc = func . location ;
2024-06-13 13:28:39 +08:00
Ok ( unifier . get_fresh_const_generic_var ( constraint , Some ( generic_name ) , Some ( loc ) ) . ty )
2022-04-18 16:02:48 +08:00
}
2023-11-28 17:37:49 +08:00
2024-06-12 14:45:03 +08:00
_ = > Err ( HashSet ::from ( [ format! (
" expression {var:?} cannot be handled as a generic parameter in global scope "
) ] ) ) ,
2022-04-18 16:02:48 +08:00
}
}
fn handle_assignment_pattern (
targets : & [ Expr ] ,
value : & Expr ,
2024-10-07 17:00:20 +08:00
resolver : Arc < dyn SymbolResolver + Send + Sync > ,
2022-04-18 16:02:48 +08:00
internal_resolver : & ResolverInternal ,
2024-10-07 17:00:20 +08:00
composer : & mut TopLevelComposer ,
2022-04-18 16:02:48 +08:00
) -> Result < ( ) , String > {
if targets . len ( ) = = 1 {
2024-10-07 17:00:20 +08:00
let target = & targets [ 0 ] ;
match & target . node {
2022-04-18 16:02:48 +08:00
ExprKind ::Name { id , .. } = > {
2024-10-07 17:00:20 +08:00
let def_list = composer . extract_def_list ( ) ;
let unifier = & mut composer . unifier ;
let primitives = & composer . primitives_ty ;
2024-06-12 14:45:03 +08:00
if let Ok ( var ) =
2024-10-07 17:00:20 +08:00
handle_typevar_definition ( value , & * resolver , & def_list , unifier , primitives )
2024-06-12 14:45:03 +08:00
{
2022-04-18 16:02:48 +08:00
internal_resolver . add_id_type ( * id , var ) ;
Ok ( ( ) )
2024-10-07 17:00:20 +08:00
} else if let Ok ( val ) = parse_parameter_default_value ( value , & * resolver ) {
2022-04-18 16:02:48 +08:00
internal_resolver . add_module_global ( * id , val ) ;
2024-10-07 17:00:20 +08:00
let ( name , def_id , _ ) = composer
. register_top_level_var (
* id ,
None ,
Some ( resolver . clone ( ) ) ,
" __main__ " ,
target . location ,
)
. unwrap ( ) ;
internal_resolver . add_id_def ( name , def_id ) ;
2022-04-18 16:02:48 +08:00
Ok ( ( ) )
} else {
2023-11-28 17:37:49 +08:00
Err ( format! ( " fails to evaluate this expression ` {:?} ` as a constant or generic parameter at {} " ,
2024-10-07 17:00:20 +08:00
target . node ,
target . location ,
2022-04-18 16:02:48 +08:00
) )
}
}
ExprKind ::List { elts , .. } | ExprKind ::Tuple { elts , .. } = > {
2024-10-07 17:00:20 +08:00
handle_assignment_pattern ( elts , value , resolver , internal_resolver , composer ) ? ;
2022-04-18 16:02:48 +08:00
Ok ( ( ) )
}
2024-10-07 17:00:20 +08:00
_ = > Err ( format! ( " assignment to {target:?} is not supported at {} " , target . location ) ) ,
2022-04-18 16:02:48 +08:00
}
} else {
match & value . node {
ExprKind ::List { elts , .. } | ExprKind ::Tuple { elts , .. } = > {
2023-12-11 14:41:58 +08:00
if elts . len ( ) = = targets . len ( ) {
2022-04-18 16:02:48 +08:00
for ( tar , val ) in targets . iter ( ) . zip ( elts ) {
handle_assignment_pattern (
std ::slice ::from_ref ( tar ) ,
val ,
2024-10-07 17:00:20 +08:00
resolver . clone ( ) ,
2022-04-18 16:02:48 +08:00
internal_resolver ,
2024-10-07 17:00:20 +08:00
composer ,
2022-04-18 16:02:48 +08:00
) ? ;
}
Ok ( ( ) )
2023-12-11 14:41:58 +08:00
} else {
Err ( format! (
" number of elements to unpack does not match (expect {}, found {}) at {} " ,
targets . len ( ) ,
elts . len ( ) ,
value . location
) )
2022-04-18 16:02:48 +08:00
}
}
2024-06-12 14:45:03 +08:00
_ = > Err ( format! ( " unpack of this expression is not supported at {} " , value . location ) ) ,
2022-04-18 16:02:48 +08:00
}
}
}
2024-10-04 13:08:09 +08:00
fn handle_global_var (
target : & Expr ,
value : Option < & Expr > ,
2024-10-07 16:52:39 +08:00
resolver : & Arc < dyn SymbolResolver + Send + Sync > ,
2024-10-04 13:08:09 +08:00
internal_resolver : & ResolverInternal ,
2024-10-07 16:52:39 +08:00
composer : & mut TopLevelComposer ,
2024-10-04 13:08:09 +08:00
) -> Result < ( ) , String > {
let ExprKind ::Name { id , .. } = target . node else {
return Err ( format! (
" global variable declaration must be an identifier (at {}) " ,
target . location ,
) ) ;
} ;
let Some ( value ) = value else {
return Err ( format! ( " global variable ` {id} ` must be initialized in its definition " ) ) ;
} ;
2024-10-07 16:52:39 +08:00
if let Ok ( val ) = parse_parameter_default_value ( value , & * * resolver ) {
2024-10-04 13:08:09 +08:00
internal_resolver . add_module_global ( id , val ) ;
2024-10-07 16:52:39 +08:00
let ( name , def_id , _ ) = composer
. register_top_level_var ( id , None , Some ( resolver . clone ( ) ) , " __main__ " , target . location )
. unwrap ( ) ;
internal_resolver . add_id_def ( name , def_id ) ;
2024-10-04 13:08:09 +08:00
Ok ( ( ) )
} else {
Err ( format! (
" failed to evaluate this expression `{:?}` as a constant at {} " ,
target . node , target . location ,
) )
}
}
2020-12-17 22:20:30 +08:00
fn main ( ) {
2023-09-06 16:34:08 +08:00
let cli = CommandLineArgs ::parse ( ) ;
2024-06-12 14:45:03 +08:00
let CommandLineArgs { file_name , threads , opt_level , emit_llvm , triple , mcpu , target_features } =
cli ;
2023-09-12 14:41:34 +08:00
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 ( ) ;
2023-10-13 11:28:30 +08:00
let threads = if is_multithreaded ( ) {
if threads = = 0 {
2024-06-12 15:13:09 +08:00
std ::thread ::available_parallelism ( ) . map ( NonZeroUsize ::get ) . unwrap_or ( 1 usize )
2023-10-13 11:28:30 +08:00
} else {
2024-06-12 15:13:09 +08:00
threads as usize
2023-10-13 11:28:30 +08:00
}
2023-10-13 14:57:09 +08:00
} else {
2023-10-13 11:28:30 +08:00
if threads ! = 1 {
2023-12-11 14:41:58 +08:00
println! ( " Warning: Number of threads specified in command-line but multithreading is disabled in LLVM at build time! Defaulting to single-threaded compilation " ) ;
2023-10-13 11:28:30 +08:00
}
1
2023-10-13 14:57:09 +08:00
} ;
2023-09-06 18:49:58 +08:00
let opt_level = match opt_level {
0 = > OptimizationLevel ::None ,
1 = > OptimizationLevel ::Less ,
2 = > OptimizationLevel ::Default ,
// The default behavior for -O<n> where n>3 defaults to O3 for both Clang and GCC
_ = > OptimizationLevel ::Aggressive ,
} ;
2021-09-22 14:30:52 +08:00
2024-07-22 00:50:55 +08:00
let target_machine_options = CodeGenTargetMachineOptions {
triple ,
cpu : mcpu ,
features : target_features ,
reloc_mode : RelocMode ::PIC ,
.. host_target_machine
} ;
2024-09-09 14:27:10 +08:00
let target_machine = target_machine_options
. create_target_machine ( opt_level )
. expect ( " couldn't create target machine " ) ;
2024-07-22 00:50:55 +08:00
2024-09-06 11:32:08 +08:00
let context = nac3core ::inkwell ::context ::Context ::create ( ) ;
2024-09-09 14:27:10 +08:00
let size_t =
context . ptr_sized_int_type ( & target_machine . get_target_data ( ) , None ) . get_bit_width ( ) ;
2024-07-22 00:50:55 +08:00
2021-12-28 10:59:17 +08:00
let program = match fs ::read_to_string ( file_name . clone ( ) ) {
2020-12-17 22:20:30 +08:00
Ok ( program ) = > program ,
2021-08-19 15:30:52 +08:00
Err ( err ) = > {
2024-10-03 12:49:07 +08:00
panic! ( " Cannot open input file: {err} " ) ;
2021-08-19 15:30:52 +08:00
}
2021-10-16 22:17:36 +08:00
} ;
2021-08-19 15:30:52 +08:00
2024-07-22 00:50:55 +08:00
let primitive : PrimitiveStore = TopLevelComposer ::make_primitives ( size_t ) . 0 ;
2022-02-21 18:27:46 +08:00
let ( mut composer , builtins_def , builtins_ty ) =
2024-08-12 18:00:23 +08:00
TopLevelComposer ::new ( vec! [ ] , vec! [ ] , ComposerConfig ::default ( ) , size_t ) ;
2021-08-27 16:25:59 +08:00
2021-09-19 16:19:16 +08:00
let internal_resolver : Arc < ResolverInternal > = ResolverInternal {
id_to_type : builtins_ty . into ( ) ,
id_to_def : builtins_def . into ( ) ,
2023-12-11 14:41:58 +08:00
module_globals : Mutex ::default ( ) ,
str_store : Mutex ::default ( ) ,
2024-06-12 14:45:03 +08:00
}
. into ( ) ;
2021-10-16 22:17:36 +08:00
let resolver =
Arc ::new ( Resolver ( internal_resolver . clone ( ) ) ) as Arc < dyn SymbolResolver + Send + Sync > ;
2021-09-22 14:45:56 +08:00
2024-08-27 10:36:51 +08:00
// Process IRRT
let irrt = load_irrt ( & context , resolver . as_ref ( ) ) ;
if emit_llvm {
irrt . write_bitcode_to_path ( Path ::new ( " irrt.bc " ) ) ;
}
// Process the Python script
2021-12-28 10:59:17 +08:00
let parser_result = parser ::parse_program ( & program , file_name . into ( ) ) . unwrap ( ) ;
2021-08-27 16:25:59 +08:00
2023-12-11 14:41:58 +08:00
for stmt in parser_result {
2022-04-18 16:02:48 +08:00
match & stmt . node {
StmtKind ::Assign { targets , value , .. } = > {
if let Err ( err ) = handle_assignment_pattern (
targets ,
value ,
2024-10-07 17:00:20 +08:00
resolver . clone ( ) ,
2022-04-18 16:02:48 +08:00
internal_resolver . as_ref ( ) ,
2024-10-07 17:00:20 +08:00
& mut composer ,
2022-04-18 16:02:48 +08:00
) {
2024-10-03 12:49:07 +08:00
panic! ( " {err} " ) ;
2021-12-01 22:44:53 +08:00
}
2024-06-12 14:45:03 +08:00
}
2024-10-04 13:08:09 +08:00
StmtKind ::AnnAssign { target , value , .. } = > {
if let Err ( err ) = handle_global_var (
target ,
value . as_ref ( ) . map ( Box ::as_ref ) ,
2024-10-07 16:52:39 +08:00
& resolver ,
2024-10-04 13:08:09 +08:00
internal_resolver . as_ref ( ) ,
2024-10-07 16:52:39 +08:00
& mut composer ,
2024-10-04 13:08:09 +08:00
) {
panic! ( " {err} " ) ;
}
}
2022-04-18 16:02:48 +08:00
// allow (and ignore) "from __future__ import annotations"
StmtKind ::ImportFrom { module , names , .. }
2024-06-12 14:45:03 +08:00
if module = = & Some ( " __future__ " . into ( ) )
& & names . len ( ) = = 1
2024-06-12 12:27:35 +08:00
& & names [ 0 ] . name = = " annotations " . into ( ) = > { }
2022-04-18 16:02:48 +08:00
_ = > {
2024-06-12 14:45:03 +08:00
let ( name , def_id , ty ) = composer
. register_top_level ( stmt , Some ( resolver . clone ( ) ) , " __main__ " , true )
. unwrap ( ) ;
2022-04-18 16:02:48 +08:00
internal_resolver . add_id_def ( name , def_id ) ;
if let Some ( ty ) = ty {
internal_resolver . add_id_type ( name , ty ) ;
2021-11-23 07:32:09 +08:00
}
}
2021-08-27 16:25:59 +08:00
}
2021-08-27 11:39:36 +08:00
}
2021-08-27 11:13:43 +08:00
2024-03-04 23:38:52 +08:00
let signature = FunSignature { args : vec ! [ ] , ret : primitive . int32 , vars : VarMap ::new ( ) } ;
2021-10-17 13:02:18 +08:00
let mut store = ConcreteTypeStore ::new ( ) ;
let mut cache = HashMap ::new ( ) ;
let signature = store . from_signature ( & mut composer . unifier , & primitive , & signature , & mut cache ) ;
let signature = store . add_cty ( signature ) ;
2024-06-26 16:45:35 +08:00
if let Err ( errors ) = composer . start_analysis ( true ) {
let error_count = errors . len ( ) ;
eprintln! ( " {error_count} error(s) occurred during top level analysis. " ) ;
for ( error_i , error ) in errors . iter ( ) . enumerate ( ) {
let error_num = error_i + 1 ;
eprintln! ( " =========== ERROR {error_num} / {error_count} ============ " ) ;
eprintln! ( " {error} " ) ;
}
eprintln! ( " ================================== " ) ;
panic! ( " top level analysis failed " ) ;
}
2021-08-27 16:25:59 +08:00
2021-09-19 16:19:16 +08:00
let top_level = Arc ::new ( composer . make_top_level_context ( ) ) ;
2021-08-25 15:30:36 +08:00
2021-08-27 16:25:59 +08:00
let instance = {
let defs = top_level . definitions . read ( ) ;
2022-02-21 18:27:46 +08:00
let mut instance = defs [ resolver
. get_identifier_def ( " run " . into ( ) )
. unwrap_or_else ( | _ | panic! ( " cannot find run() entry point " ) )
. 0 ]
. write ( ) ;
2024-06-12 14:45:03 +08:00
let TopLevelDef ::Function { instance_to_stmt , instance_to_symbol , .. } = & mut * instance
else {
2021-08-27 16:25:59 +08:00
unreachable! ( )
2023-12-12 13:38:27 +08:00
} ;
instance_to_symbol . insert ( String ::new ( ) , " run " . to_string ( ) ) ;
instance_to_stmt [ " " ] . clone ( )
2021-08-27 16:25:59 +08:00
} ;
2021-09-19 16:19:16 +08:00
2024-07-22 00:50:55 +08:00
let llvm_options = CodeGenLLVMOptions { opt_level , target : target_machine_options } ;
2023-09-11 13:12:46 +08:00
2021-08-19 15:30:52 +08:00
let task = CodeGenTask {
2023-12-11 14:41:58 +08:00
subst : Vec ::default ( ) ,
2021-08-19 15:30:52 +08:00
symbol_name : " run " . to_string ( ) ,
2021-08-27 16:25:59 +08:00
body : instance . body ,
2021-08-19 15:30:52 +08:00
signature ,
2021-08-27 16:25:59 +08:00
resolver ,
2021-10-17 13:02:18 +08:00
store ,
unifier_index : instance . unifier_id ,
2021-08-27 16:25:59 +08:00
calls : instance . calls ,
2021-11-20 19:50:25 +08:00
id : 0 ,
2021-08-19 15:30:52 +08:00
} ;
2021-08-27 16:25:59 +08:00
2023-12-11 14:41:58 +08:00
let membuffers : Arc < Mutex < Vec < Vec < u8 > > > > = Arc ::default ( ) ;
2022-01-09 02:11:33 +08:00
let membuffer = membuffers . clone ( ) ;
2022-02-13 17:21:42 +08:00
2022-01-09 02:11:33 +08:00
let f = Arc ::new ( WithCall ::new ( Box ::new ( move | module | {
let buffer = module . write_bitcode_to_memory ( ) ;
let buffer = buffer . as_slice ( ) . into ( ) ;
membuffer . lock ( ) . push ( buffer ) ;
2021-08-19 15:30:52 +08:00
} ) ) ) ;
2021-10-16 22:17:36 +08:00
let threads = ( 0 .. threads )
2024-07-22 00:50:55 +08:00
. map ( | i | Box ::new ( DefaultCodeGenerator ::new ( format! ( " module {i} " ) , size_t ) ) )
2021-10-16 22:17:36 +08:00
. collect ( ) ;
2023-12-08 17:43:32 +08:00
let ( registry , handles ) = WorkerRegistry ::create_workers ( threads , top_level , & llvm_options , & f ) ;
2021-08-19 15:30:52 +08:00
registry . add_task ( task ) ;
registry . wait_tasks_complete ( handles ) ;
2021-09-22 14:30:52 +08:00
2024-08-27 10:36:51 +08:00
// Link all modules together into `main`
2022-01-09 02:11:33 +08:00
let buffers = membuffers . lock ( ) ;
let main = context
. create_module_from_ir ( MemoryBuffer ::create_from_memory_range ( & buffers [ 0 ] , " main " ) )
. unwrap ( ) ;
2023-09-15 13:26:15 +08:00
if emit_llvm {
main . write_bitcode_to_path ( Path ::new ( " main.bc " ) ) ;
}
for ( idx , buffer ) in buffers . iter ( ) . skip ( 1 ) . enumerate ( ) {
2022-01-09 02:11:33 +08:00
let other = context
. create_module_from_ir ( MemoryBuffer ::create_from_memory_range ( buffer , " main " ) )
. unwrap ( ) ;
2023-09-15 13:26:15 +08:00
if emit_llvm {
2023-12-11 14:41:58 +08:00
other . write_bitcode_to_path ( Path ::new ( & format! ( " module {idx} .bc " ) ) ) ;
2023-09-15 13:26:15 +08:00
}
2022-01-09 02:11:33 +08:00
main . link_in_module ( other ) . unwrap ( ) ;
}
2023-09-29 16:41:32 +08:00
main . link_in_module ( irrt ) . unwrap ( ) ;
2022-01-09 02:11:33 +08:00
2024-08-27 10:36:51 +08:00
// Private all functions except "run"
2022-01-09 02:11:33 +08:00
let mut function_iter = main . get_first_function ( ) ;
while let Some ( func ) = function_iter {
if func . count_basic_blocks ( ) > 0 & & func . get_name ( ) . to_str ( ) . unwrap ( ) ! = " run " {
2024-09-06 11:32:08 +08:00
func . set_linkage ( Linkage ::Private ) ;
2022-01-09 02:11:33 +08:00
}
function_iter = func . get_next_function ( ) ;
}
2024-08-27 10:36:51 +08:00
// Optimize `main`
2023-09-11 13:14:35 +08:00
let pass_options = PassBuilderOptions ::create ( ) ;
pass_options . set_merge_functions ( true ) ;
2023-09-21 15:34:05 +08:00
let passes = format! ( " default<O {} > " , opt_level as u32 ) ;
let result = main . run_passes ( passes . as_str ( ) , & target_machine , pass_options ) ;
2023-09-11 13:14:35 +08:00
if let Err ( err ) = result {
panic! ( " Failed to run optimization for module `main`: {} " , err . to_string ( ) ) ;
}
2024-08-27 10:36:51 +08:00
// Write output
2022-01-09 02:11:33 +08:00
target_machine
2022-02-21 18:27:46 +08:00
. write_to_file ( & main , FileType ::Object , Path ::new ( " module.o " ) )
2022-01-09 02:11:33 +08:00
. expect ( " couldn't write module to file " ) ;
2020-12-17 22:20:30 +08:00
}