diff --git a/hercules_cg/src/device.rs b/hercules_cg/src/device.rs new file mode 100644 index 0000000000000000000000000000000000000000..7dbeeeda77182e833b258f4f78109e7e3abb185e --- /dev/null +++ b/hercules_cg/src/device.rs @@ -0,0 +1,24 @@ +extern crate hercules_ir; + +use self::hercules_ir::*; + +/* + * Top level function to definitively place functions onto devices. A function + * may store a device placement, but only optionally - this function assigns + * devices to the rest of the functions. + */ +pub fn device_placement(functions: &Vec<Function>, callgraph: &CallGraph) -> Vec<Device> { + let mut devices = vec![]; + + for (idx, function) in functions.into_iter().enumerate() { + if let Some(device) = function.device { + devices.push(device); + } else if function.entry || callgraph.num_callees(FunctionID::new(idx)) != 0 { + devices.push(Device::AsyncRust); + } else { + devices.push(Device::LLVM); + } + } + + devices +} diff --git a/hercules_cg/src/lib.rs b/hercules_cg/src/lib.rs index 9013eff7fd2c310388d9869050b38d235a4e205c..952ce368fac9764f7faba2383a72e5584202f6eb 100644 --- a/hercules_cg/src/lib.rs +++ b/hercules_cg/src/lib.rs @@ -1,9 +1,11 @@ #![feature(if_let_guard, let_chains)] pub mod cpu; +pub mod device; pub mod mem; pub mod rt; pub use crate::cpu::*; +pub use crate::device::*; pub use crate::mem::*; pub use crate::rt::*; diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index f6356dfdbfebe14faba3049dc745ea4a519759fa..c0faec591bdc6d7f3ba0079395fa855cbc9012c8 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -333,9 +333,8 @@ pub enum Schedule { pub enum Device { LLVM, NVVM, - // Internal nodes in the call graph are lowered to async Rust code that - // calls device functions (leaf nodes in the call graph), possibly - // concurrently. + // Entry functions are lowered to async Rust code that calls device + // functions (leaf nodes in the call graph), possibly concurrently. AsyncRust, } diff --git a/hercules_opt/src/pass.rs b/hercules_opt/src/pass.rs index ce53916bee5afcf19ca84f0d504ba87e5effedde..b85835cf295620615aee586982d1d6179d3e8d29 100644 --- a/hercules_opt/src/pass.rs +++ b/hercules_opt/src/pass.rs @@ -864,13 +864,25 @@ impl PassManager { let memory_objects_mutable = memory_objects_mutability(&self.module, &callgraph, &memory_objects); + let devices = device_placement(&self.module.functions, &callgraph); + let mut rust_rt = String::new(); let mut llvm_ir = String::new(); for idx in 0..self.module.functions.len() { - if self.module.functions[idx].entry - || callgraph.num_callees(FunctionID::new(idx)) != 0 - { - rt_codegen( + match devices[idx] { + Device::LLVM => cpu_codegen( + &self.module.functions[idx], + &self.module.types, + &self.module.constants, + &self.module.dynamic_constants, + &reverse_postorders[idx], + &typing[idx], + &control_subgraphs[idx], + &bbs[idx], + &mut llvm_ir, + ) + .unwrap(), + Device::AsyncRust => rt_codegen( FunctionID::new(idx), &self.module, &reverse_postorders[idx], @@ -882,21 +894,8 @@ impl PassManager { &memory_objects_mutable, &mut rust_rt, ) - .unwrap(); - } else { - // TODO: determine which backend to use for function. - cpu_codegen( - &self.module.functions[idx], - &self.module.types, - &self.module.constants, - &self.module.dynamic_constants, - &reverse_postorders[idx], - &typing[idx], - &control_subgraphs[idx], - &bbs[idx], - &mut llvm_ir, - ) - .unwrap(); + .unwrap(), + _ => todo!(), } } println!("{}", llvm_ir);