Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --print-ir-before-all command line argument #31

Merged
merged 10 commits into from
Dec 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xrcf/script/* linguist-vendored
5 changes: 3 additions & 2 deletions .github/workflows/Release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Release
name: release

# The build always runs, but only releases on tag, see the last step.
on:
Expand Down Expand Up @@ -76,7 +76,8 @@ jobs:
id: release
shell: bash

- uses: softprops/action-gh-release@v2
# Hardcoded commit hash to mitigate supply chain attacks.
- uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
if: startsWith(github.ref, 'refs/tags/')
with:
fail_on_unmatched_files: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml → .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ci
name: check

on:
push:
Expand Down
48 changes: 39 additions & 9 deletions arnoldc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::io::Read;
use xrcf::convert::RewriteResult;
use xrcf::init_subscriber;
use xrcf::Passes;
use xrcf::TransformOptions;

use crate::transform::parse_and_transform;

Expand All @@ -33,7 +34,7 @@ struct ArnoldcArgs {
}

fn cli() -> Command {
let cli = Command::new("arnoldc").args(xrcf::default_passes());
let cli = Command::new("arnoldc").args(xrcf::default_arguments());
let cli = ArnoldcArgs::augment_args(cli);
cli
}
Expand Down Expand Up @@ -74,6 +75,7 @@ fn main() {
init_tracing(tracing::Level::INFO);
}
let passes = passes_from_args(args, matches.clone());
let options = TransformOptions::from_args(matches.clone(), passes.clone());

let input = matches.get_one::<String>("input").unwrap();

Expand All @@ -85,7 +87,7 @@ fn main() {
std::fs::read_to_string(input).unwrap()
};

let result = parse_and_transform(&input_text, &passes).unwrap();
let result = parse_and_transform(&input_text, &options).unwrap();
let result = match result {
RewriteResult::Changed(op) => op.op.try_read().unwrap().to_string(),
RewriteResult::Unchanged => input_text.to_string(),
Expand All @@ -98,22 +100,36 @@ mod tests {
use super::*;
use anyhow::Result;
use indoc::indoc;
use std::panic::Location;
use std::sync::Arc;
use std::sync::RwLock;
use xrcf::convert::RewriteResult;
use xrcf::tester::Tester;

fn run_app(args: Vec<&str>, input_text: &str) -> Result<RewriteResult> {
fn run_app(
out: Option<Arc<RwLock<dyn std::io::Write + Send>>>,
args: Vec<&str>,
input_text: &str,
) -> Result<RewriteResult> {
let cli = cli();
let args_owned: Vec<String> = args.iter().map(|&s| s.to_string()).collect();
let _matches = cli.try_get_matches_from(args_owned)?;
let passes = Passes::from_convert_vec(args);
let result = parse_and_transform(input_text, &passes)?;
let passes = Passes::from_convert_vec(args.clone());
let mut options = TransformOptions::from_passes(passes.clone());
if args.contains(&"--print-ir-before-all") {
options.set_print_ir_before_all(true);
}
if let Some(out) = out {
options.set_writer(out);
}
let result = parse_and_transform(input_text, &options)?;
Ok(result)
}

#[test]
fn test_help() {
let args = vec!["xr-example", "--help"];
let result = run_app(args, "");
let result = run_app(None, args, "");
let err = match result {
Ok(_) => panic!("Expected an error"),
Err(e) => e,
Expand All @@ -126,7 +142,8 @@ mod tests {

#[test]
fn test_invalid_args() {
let result = run_app(vec!["xr-example", "--invalid-flag"], "");
let args = vec!["xr-example", "--invalid-flag"];
let result = run_app(None, args, "");
assert!(result.is_err());
}

Expand All @@ -141,9 +158,14 @@ mod tests {
"#
};
// The order of these passes is important.
let args = vec!["--convert-func-to-llvm", "--convert-mlir-to-llvmir"];
let args = vec![
"--convert-func-to-llvm",
"--convert-mlir-to-llvmir",
"--print-ir-before-all",
];
tracing::info!("\nBefore {args:?}:\n{src}");
let result = run_app(args.clone(), src);
let out: Arc<RwLock<Vec<u8>>> = Arc::new(RwLock::new(Vec::new()));
let result = run_app(Some(out.clone()), args.clone(), &src);
assert!(result.is_ok());
let actual = match result.unwrap() {
RewriteResult::Changed(op) => {
Expand All @@ -154,5 +176,13 @@ mod tests {
};
tracing::info!("\nAfter {args:?}:\n{actual}");
assert!(actual.contains("define i32 @main"));

let printed = out.try_read().unwrap();
let printed = String::from_utf8(printed.clone()).unwrap();
let expected = indoc! {r#"
// ----- // IR Dump before convert-func-to-llvm //----- //
// ----- // IR Dump before convert-mlir-to-llvmir //----- //
"#};
Tester::check_lines_contain(&printed, expected, Location::caller());
}
}
12 changes: 7 additions & 5 deletions arnoldc/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ use xrcf::parser::ParserDispatch;
use xrcf::parser::TokenKind;
use xrcf::transform;
use xrcf::DefaultTransformDispatch;
use xrcf::Passes;
use xrcf::SinglePass;
use xrcf::TransformDispatch;

use xrcf::TransformOptions;
pub struct ArnoldParserDispatch;

fn is_function_call<T: ParserDispatch>(parser: &Parser<T>) -> bool {
Expand Down Expand Up @@ -123,10 +122,10 @@ fn preprocess(src: &str) -> String {
result
}

pub fn parse_and_transform(src: &str, passes: &Passes) -> Result<RewriteResult> {
pub fn parse_and_transform(src: &str, options: &TransformOptions) -> Result<RewriteResult> {
let src = preprocess(src);
let op = Parser::<ArnoldParserDispatch>::parse(&src)?;
let result = transform::<ArnoldTransformDispatch>(op, passes)?;
let result = transform::<ArnoldTransformDispatch>(op, options)?;
Ok(result)
}

Expand All @@ -138,6 +137,7 @@ mod tests {
use std::panic::Location;
use tracing;
use xrcf::tester::Tester;
use xrcf::Passes;

fn flags() -> Vec<&'static str> {
vec!["--convert-arnold-to-mlir"]
Expand Down Expand Up @@ -195,12 +195,14 @@ mod tests {
fn print_heading(msg: &str, src: &str, passes: &Passes) {
tracing::info!("{msg} ({passes}):\n```\n{src}\n```\n");
}

fn test_transform(src: &str, passes: Vec<&str>) -> (Arc<RwLock<dyn Op>>, String) {
Tester::init_tracing();
let src = src.trim();
let passes = Passes::from_vec(passes);
print_heading("Before", src, &passes);
let result = parse_and_transform(src, &passes).unwrap();
let options = TransformOptions::from_passes(passes.clone());
let result = parse_and_transform(src, &options).unwrap();
let new_root_op = match result {
RewriteResult::Changed(changed_op) => changed_op.op,
RewriteResult::Unchanged => {
Expand Down
13 changes: 8 additions & 5 deletions xrcf-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use xrcf::parser::Parser;
use xrcf::transform;
use xrcf::DefaultTransformDispatch;
use xrcf::Passes;
use xrcf::TransformOptions;

/// An example XRCF compiler that contains all default passes
#[derive(Args, Debug)]
Expand All @@ -23,7 +24,7 @@ struct XRCFArgs {
}

fn cli() -> Command {
let cli = Command::new("xrcf").args(xrcf::default_passes());
let cli = Command::new("xrcf").args(xrcf::default_arguments());
let cli = XRCFArgs::augment_args(cli);
cli
}
Expand All @@ -32,10 +33,10 @@ fn remove_comments(src: &str) -> String {
src.lines().filter(|line| !line.starts_with("//")).collect()
}

fn parse_and_transform(src: &str, passes: &Passes) -> String {
fn parse_and_transform(src: &str, options: &TransformOptions) -> String {
let src = remove_comments(src);
let module = Parser::<DefaultParserDispatch>::parse(&src).unwrap();
let result = transform::<DefaultTransformDispatch>(module, &passes).unwrap();
let result = transform::<DefaultTransformDispatch>(module, options).unwrap();
let result = match result {
RewriteResult::Changed(op) => op.op.try_read().unwrap().to_string(),
RewriteResult::Unchanged => src.to_string(),
Expand All @@ -55,6 +56,7 @@ fn main() {
let args = std::env::args_os();
let passes = Passes::from_convert_args(args);
let matches = cli.get_matches();
let options = TransformOptions::from_args(matches.clone(), passes.clone());
if matches.get_flag("debug") {
init_tracing(tracing::Level::DEBUG);
} else {
Expand All @@ -71,7 +73,7 @@ fn main() {
std::fs::read_to_string(input).unwrap()
};

let result = parse_and_transform(&input_text, &passes);
let result = parse_and_transform(&input_text, &options);
println!("{result}");
}

Expand All @@ -85,7 +87,8 @@ mod tests {
let args_owned: Vec<String> = args.iter().map(|&s| s.to_string()).collect();
let _matches = cli.try_get_matches_from(args_owned)?;
let passes = Passes::from_convert_vec(args);
let result = parse_and_transform(input_text, &passes);
let options = TransformOptions::from_args(_matches.clone(), passes.clone());
let result = parse_and_transform(input_text, &options);
Ok(result)
}

Expand Down
8 changes: 6 additions & 2 deletions xrcf/script/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Trigger a release
#

set -e
set -e -u -o pipefail

# We have to run this locally because tags created from workflows do not
# trigger new workflows.
Expand All @@ -28,7 +28,11 @@ echo ""
echo "ENSURE 'cargo publish' SUCCEEDED"
echo ""

NOTES="See [CHANGELOG.md](https://github.com/rikhuijzer/xrcf/blob/main/CHANGELOG.md) for more information."
NOTES="\`xrcf-bin\` is a compiler that can compile basic MLIR programs to LLVM IR, and can be used for testing the xrcf package. This binary contains all the default passes such as \`--convert-func-to-llvm\`.

\`arnoldc\` is a compiler that can compile basic ArnoldC programs to LLVM IR. Next to the default passes, this binary contains the pass \`--convert-arnold-to-mlir\` which can lower ArnoldC programs to MLIR. From there, the default passes such as \`--convert-func-to-llvm\` can be used to lower ArnoldC to LLVM IR.

See [CHANGELOG.md](https://github.com/rikhuijzer/xrcf/blob/main/CHANGELOG.md) for more information about changes since the last release."

echo "Ready to create a new tag, which WILL TRIGGER A RELEASE with the following release notes:"
echo "\"$NOTES\""
Expand Down
3 changes: 2 additions & 1 deletion xrcf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ pub mod targ3t;
pub mod tester;
mod transform;

pub use transform::default_passes;
pub use transform::default_arguments;
pub use transform::init_subscriber;
pub use transform::transform;
pub use transform::DefaultTransformDispatch;
pub use transform::Passes;
pub use transform::SinglePass;
pub use transform::TransformDispatch;
pub use transform::TransformOptions;

/// Dialects can define new operations, attributes, and types.
/// Each dialect is given an unique namespace that is prefixed.
Expand Down
4 changes: 3 additions & 1 deletion xrcf/src/tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::parser::Parser;
use crate::transform;
use crate::DefaultTransformDispatch;
use crate::Passes;
use crate::TransformOptions;
use std::cmp::max;
use std::panic::Location;
use std::sync::Arc;
Expand Down Expand Up @@ -122,7 +123,8 @@ impl Tester {
}
}
let passes = Passes::from_convert_vec(arguments.clone());
let result = transform::<DefaultTransformDispatch>(module.clone(), &passes).unwrap();
let options = TransformOptions::from_passes(passes);
let result = transform::<DefaultTransformDispatch>(module.clone(), &options).unwrap();
let new_root_op = match result {
RewriteResult::Changed(changed_op) => changed_op.op,
RewriteResult::Unchanged => {
Expand Down
Loading
Loading