Skip to content
Snippets Groups Projects
Commit 47e92dd2 authored by Aaron Councilman's avatar Aaron Councilman
Browse files

Add ability to compile .hir file through Juno Compiler

parent 34174fac
No related branches found
No related tags found
1 merge request!52Setup for CI
Pipeline #200257 passed
Showing
with 194 additions and 73 deletions
......@@ -369,6 +369,18 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "dot"
version = "0.1.0"
dependencies = [
"async-std",
"clap",
"hercules_rt",
"juno_build",
"rand",
"with_builtin_macros",
]
[[package]]
name = "either"
version = "1.13.0"
......@@ -682,6 +694,7 @@ dependencies = [
name = "juno_build"
version = "0.1.0"
dependencies = [
"hercules_ir",
"hercules_rt",
"juno_frontend",
"with_builtin_macros",
......@@ -835,6 +848,18 @@ dependencies = [
"vob",
]
[[package]]
name = "matmul"
version = "0.1.0"
dependencies = [
"async-std",
"clap",
"hercules_rt",
"juno_build",
"rand",
"with_builtin_macros",
]
[[package]]
name = "memchr"
version = "2.7.4"
......
......@@ -12,8 +12,8 @@ members = [
#"hercules_test/hercules_interpreter",
#"hercules_test/hercules_tests",
#"hercules_samples/dot",
#"hercules_samples/matmul",
"hercules_samples/dot",
"hercules_samples/matmul",
#"hercules_samples/fac",
"juno_frontend",
......@@ -22,4 +22,4 @@ members = [
#"juno_samples/matmul",
"juno_samples/simple3",
]
\ No newline at end of file
]
......@@ -4,8 +4,13 @@ version = "0.1.0"
authors = ["Russel Arbore <rarbore2@illinois.edu>"]
edition = "2021"
[build-dependencies]
juno_build = { path = "../../juno_build" }
[dependencies]
clap = { version = "*", features = ["derive"] }
juno_build = { path = "../../juno_build" }
hercules_rt = { path = "../../hercules_rt" }
rand = "*"
async-std = "*"
with_builtin_macros = "0.1.0"
use std::env::current_dir;
extern crate juno_build;
use juno_build::JunoCompiler;
fn main() {
println!(
"cargo::rustc-link-search=native={}",
current_dir().unwrap().display()
);
println!("cargo::rustc-link-lib=static=dot");
println!("cargo::rerun-if-changed=dot.hman");
println!("cargo::rerun-if-changed=libdot.a");
JunoCompiler::new()
.ir_in_src("dot.hir")
.unwrap()
.build()
.unwrap();
}
File moved
extern crate async_std;
extern crate clap;
extern crate hercules_rt;
extern crate juno_build;
// To compile currently, run from the Hercules project root directory:
// cargo run --bin hercules_driver hercules_samples/dot/dot.hir "Codegen(\"hercules_samples/dot\",\"dot\")"
// Then, you can execute this example with:
// cargo run --bin dot
hercules_rt::use_hman!("hercules_samples/dot/dot.hman");
juno_build::juno!("dot");
fn main() {
async_std::task::block_on(async {
......
......@@ -4,8 +4,13 @@ version = "0.1.0"
authors = ["Russel Arbore <rarbore2@illinois.edu>"]
edition = "2021"
[build-dependencies]
juno_build = { path = "../../juno_build" }
[dependencies]
clap = { version = "*", features = ["derive"] }
juno_build = { path = "../../juno_build" }
hercules_rt = { path = "../../hercules_rt" }
rand = "*"
async-std = "*"
with_builtin_macros = "0.1.0"
use std::env::current_dir;
extern crate juno_build;
use juno_build::JunoCompiler;
fn main() {
println!(
"cargo::rustc-link-search=native={}",
current_dir().unwrap().display()
);
println!("cargo::rustc-link-lib=static=fac");
println!("cargo::rerun-if-changed=fac.hman");
println!("cargo::rerun-if-changed=libfac.a");
JunoCompiler::new()
.ir_in_src("fac.hir")
.unwrap()
.build()
.unwrap();
}
File moved
extern crate async_std;
extern crate clap;
extern crate hercules_rt;
extern crate juno_build;
// To compile currently, run from the Hercules project root directory:
// cargo run --bin hercules_driver hercules_samples/fac/fac.hir "Codegen(\"hercules_samples/fac\",\"fac\")"
// Then, you can execute this example with:
// cargo run --bin fac
hercules_rt::use_hman!("hercules_samples/fac/fac.hman");
juno_build::juno!("fac");
fn main() {
async_std::task::block_on(async {
......
......@@ -4,8 +4,13 @@ version = "0.1.0"
authors = ["Russel Arbore <rarbore2@illinois.edu>"]
edition = "2021"
[build-dependencies]
juno_build = { path = "../../juno_build" }
[dependencies]
clap = { version = "*", features = ["derive"] }
juno_build = { path = "../../juno_build" }
hercules_rt = { path = "../../hercules_rt" }
rand = "*"
async-std = "*"
with_builtin_macros = "0.1.0"
use std::env::current_dir;
extern crate juno_build;
use juno_build::JunoCompiler;
fn main() {
println!(
"cargo::rustc-link-search=native={}",
current_dir().unwrap().display()
);
println!("cargo::rustc-link-lib=static=matmul");
println!("cargo::rerun-if-changed=matmul.hman");
println!("cargo::rerun-if-changed=libmatmul.a");
JunoCompiler::new()
.ir_in_src("matmul.hir")
.unwrap()
.build()
.unwrap();
}
......@@ -2,13 +2,9 @@
extern crate async_std;
extern crate clap;
extern crate hercules_rt;
extern crate juno_build;
// To compile currently, run from the Hercules project root directory:
// cargo run --bin hercules_driver hercules_samples/matmul/matmul.hir "Codegen(\"hercules_samples/matmul\",\"matmul\")"
// Then, you can execute this example with:
// cargo run --bin matmul
hercules_rt::use_hman!("hercules_samples/matmul/matmul.hman");
juno_build::juno!("matmul");
fn main() {
async_std::task::block_on(async {
......
......@@ -7,4 +7,5 @@ edition = "2021"
[dependencies]
juno_frontend = { path = "../juno_frontend" }
hercules_rt = { path = "../hercules_rt" }
hercules_ir = { path = "../hercules_ir" }
with_builtin_macros = "0.1.0"
extern crate hercules_ir;
extern crate hercules_rt;
use juno_compiler::*;
use std::env::{current_dir, var};
use std::fmt::Write;
use std::fs::create_dir_all;
use std::fs::{create_dir_all, read_to_string};
use std::path::{Path, PathBuf};
use with_builtin_macros::with_builtin;
// JunoCompiler is used to compile juno files into a library and manifest file appropriately to
// import the definitions into a rust project via the juno! macro defined below
// You can also specify a Hercules IR file instead of a Juno file and this will compile that IR
// file (though in that case a schedule is not supported)
pub struct JunoCompiler {
ir_src_path: Option<PathBuf>,
src_path: Option<PathBuf>,
out_path: Option<PathBuf>,
verify: JunoVerify,
......@@ -21,6 +26,7 @@ pub struct JunoCompiler {
impl JunoCompiler {
pub fn new() -> Self {
JunoCompiler {
ir_src_path: None,
src_path: None,
out_path: None,
verify: JunoVerify::None,
......@@ -32,6 +38,33 @@ impl JunoCompiler {
// Sets the name of the Juno file, this file should be contained in the src/
// file of the package that the JunoCompiler is used in the build script of
pub fn file_in_src<P>(mut self, file: P) -> Result<Self, String>
where
P: AsRef<Path>,
{
self.src_path = Some(Self::make_src_path(&file)?);
self.ir_src_path = None;
self.out_path = Some(Self::get_out_path(&file)?);
Self::print_cargo_info(file);
Ok(self)
}
// Sets the name of the input Hercules IR file which is contained in the src/ directory of the
// package that the JunoCompiler is used in the build script of
pub fn ir_in_src<P>(mut self, file: P) -> Result<Self, String>
where
P: AsRef<Path>,
{
self.ir_src_path = Some(Self::make_src_path(&file)?);
self.src_path = None;
self.out_path = Some(Self::get_out_path(&file)?);
Self::print_cargo_info(file);
Ok(self)
}
// Construct the path to a file in the source directory
fn make_src_path<P>(file: P) -> Result<PathBuf, String>
where
P: AsRef<Path>,
{
......@@ -48,34 +81,45 @@ impl JunoCompiler {
};
path.push("src");
path.push(file.as_ref());
self.src_path = Some(path);
// We also set the output file in this process, under the OUT_DIR cargo provides
Ok(path)
}
// Construct the path to the output directory, under the OUT_DIR cargo provides
fn get_out_path<P>(file: P) -> Result<PathBuf, String>
where
P: AsRef<Path>,
{
let mut out = PathBuf::new();
out.push(var("OUT_DIR").unwrap());
out.push(file.as_ref().parent().unwrap().to_str().unwrap());
let Ok(()) = create_dir_all(&out) else {
return Err("Failed to create output directory.".to_string());
};
self.out_path = Some(out);
Ok(out)
}
// Tell cargo to rerun if the Juno file changes
// Prints information to tell cargo the following
// - Rerun if the source file changes
// - Add the output directory to its linker search
// - Link the compiled library file
// Tell cargo to rerun if the Juno file changes
fn print_cargo_info<P>(src_file: P)
where
P: AsRef<Path>,
{
println!(
"cargo::rerun-if-changed=src/{}",
file.as_ref().to_str().unwrap()
src_file.as_ref().to_str().unwrap()
);
// Tell cargo to include the output directory in its linker search
// (and to link the resulting library)
println!(
"cargo::rustc-link-search=native={}",
var("OUT_DIR").unwrap()
);
println!(
"cargo::rustc-link-lib=static={}",
file.as_ref().file_stem().unwrap().to_str().unwrap()
src_file.as_ref().file_stem().unwrap().to_str().unwrap()
);
Ok(self)
}
pub fn verify(mut self, enabled: bool) -> Self {
......@@ -139,7 +183,8 @@ impl JunoCompiler {
// Builds the juno file into a libary and a manifest file.
pub fn build(self) -> Result<(), String> {
let JunoCompiler {
src_path: Some(src_path),
ir_src_path: ir_src_path,
src_path: src_path,
out_path: Some(out_path),
verify,
x_dot,
......@@ -149,12 +194,35 @@ impl JunoCompiler {
return Err("No source file specified.".to_string());
};
let src_file = src_path.to_str().unwrap().to_string();
let out_dir = out_path.to_str().unwrap().to_string();
match compile(src_file, verify, x_dot, schedule, out_dir) {
Ok(()) => Ok(()),
Err(errs) => Err(format!("{}", errs)),
if let Some(src_path) = src_path {
let src_file = src_path.to_str().unwrap().to_string();
match compile(src_file, verify, x_dot, schedule, out_dir) {
Ok(()) => Ok(()),
Err(errs) => Err(format!("{}", errs)),
}
} else {
let Some(ir_src_path) = ir_src_path else {
return Err("No source file specified.".to_string());
};
let ir_src_file = ir_src_path.to_str().unwrap().to_string();
let ir_src_path = Path::new(&ir_src_file);
let module_name = String::from(ir_src_path.file_stem().unwrap().to_str().unwrap());
let Ok(contents) = read_to_string(&ir_src_path) else {
return Err("Unable to open and read input file.".to_string());
};
let Ok(ir_mod) = hercules_ir::parse::parse(&contents) else {
return Err("Unable to parse Hercules IR file.".to_string());
};
match compile_ir(ir_mod, None, verify, x_dot, schedule, out_dir, module_name) {
Ok(()) => Ok(()),
Err(errs) => Err(format!("{}", errs)),
}
}
}
}
......
......@@ -14,6 +14,8 @@ extern crate hercules_ir;
use std::fmt;
use std::path::Path;
use juno_scheduler::FunctionMap;
pub enum JunoVerify {
None,
JunoOpts,
......@@ -96,6 +98,26 @@ pub fn compile(
};
let (module, func_info) = codegen::codegen_program(prg);
compile_ir(
module,
Some(func_info),
verify,
x_dot,
schedule,
output_dir,
module_name,
)
}
pub fn compile_ir(
module: hercules_ir::ir::Module,
func_info: Option<FunctionMap>,
verify: JunoVerify,
x_dot: bool,
schedule: JunoSchedule,
output_dir: String,
module_name: String,
) -> Result<(), ErrorMessage> {
let mut pm = match schedule {
JunoSchedule::None => hercules_opt::pass::PassManager::new(module),
JunoSchedule::DefaultSchedule => {
......@@ -103,16 +125,24 @@ pub fn compile(
pm.make_plans();
pm
}
JunoSchedule::Schedule(file) => match juno_scheduler::schedule(&module, func_info, file) {
Ok(plans) => {
let mut pm = hercules_opt::pass::PassManager::new(module);
pm.set_plans(plans);
pm
}
Err(msg) => {
return Err(ErrorMessage::SchedulingError(msg));
JunoSchedule::Schedule(file) => {
let Some(func_info) = func_info else {
return Err(ErrorMessage::SchedulingError(
"Cannot schedule, no function information provided".to_string(),
));
};
match juno_scheduler::schedule(&module, func_info, file) {
Ok(plans) => {
let mut pm = hercules_opt::pass::PassManager::new(module);
pm.set_plans(plans);
pm
}
Err(msg) => {
return Err(ErrorMessage::SchedulingError(msg));
}
}
},
}
};
if verify.verify() || verify.verify_all() {
pm.add_pass(hercules_opt::pass::Pass::Verify);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment