Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
18 changes: 18 additions & 0 deletions .github/actions/download-noir-ssa/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Download noir-ssa
description: Downloads the noir-ssa binary from an artifact and adds it to the path

runs:
using: composite
steps:
- name: Download noir-ssa binary
uses: actions/download-artifact@v4
with:
name: noir-ssa
path: ./noir-ssa

- name: Set noir-ssa on PATH
shell: bash
run: |
noir_binary="${{ github.workspace }}/noir-ssa/noir-ssa"
chmod +x $noir_binary
echo "$(dirname $noir_binary)" >> $GITHUB_PATH
38 changes: 36 additions & 2 deletions .github/workflows/test-js-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ jobs:
cache-on-failure: true
save-if: ${{ github.event_name != 'merge_group' }}

- name: Build noir-execute
- name: Build artifact
run: cargo build --package noir_artifact_cli --release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -111,6 +111,37 @@ jobs:
path: ./target/release/noir-execute
retention-days: 3

build-noir-ssa:
runs-on: ubuntu-22.04
timeout-minutes: 30
permissions:
contents: read

steps:
- name: Checkout Noir repo
uses: actions/checkout@v5

- name: Setup toolchain
uses: dtolnay/[email protected]

- uses: Swatinem/rust-cache@v2
with:
key: x86_64-unknown-linux-gnu
cache-on-failure: true
save-if: ${{ github.event_name != 'merge_group' }}

- name: Build artifact
run: cargo build --package noir_ssa_cli --release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: noir-ssa
path: ./target/release/noir-ssa
retention-days: 3

build-noirc-abi:
runs-on: ubuntu-22.04
timeout-minutes: 30
Expand Down Expand Up @@ -533,7 +564,7 @@ jobs:
test-examples:
name: Example scripts
runs-on: ubuntu-24.04
needs: [build-nargo, build-noir-execute, build-acvm-js, build-noirc-abi]
needs: [build-nargo, build-noir-execute, build-noir-ssa, build-acvm-js, build-noirc-abi]
timeout-minutes: 30
permissions:
contents: read
Expand Down Expand Up @@ -567,6 +598,9 @@ jobs:
- name: Download noir-execute binary
uses: ./.github/actions/download-noir-execute

- name: Download noir-ssa binary
uses: ./.github/actions/download-noir-ssa

- name: Download acvm_js package artifact
uses: actions/download-artifact@v4
with:
Expand Down
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ members = [
# Utility crates
"utils/iter-extended",

"tooling/ssa_cli",
"tooling/ssa_fuzzer",
"tooling/ssa_fuzzer/fuzzer",
"tooling/ssa_verification",
Expand All @@ -52,6 +53,7 @@ default-members = [
"tooling/nargo_cli",
"tooling/acvm_cli",
"tooling/artifact_cli",
"tooling/ssa_cli",
"tooling/profiler",
"tooling/inspector",
]
Expand Down
36 changes: 31 additions & 5 deletions compiler/noirc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ pub use position::{Located, Location, Position, Span, Spanned};
pub use reporter::{CustomDiagnostic, DiagnosticKind};
use std::io::Write;

/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received.
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
pub fn print_to_stdout(args: std::fmt::Arguments) {
let mut stdout = std::io::stdout();
if let Err(e) = stdout.write_fmt(args) {
pub fn print_args_or_exit<W: Write>(args: std::fmt::Arguments, mut out: W) {
if let Err(e) = out.write_fmt(args) {
if e.kind() == std::io::ErrorKind::BrokenPipe {
// Gracefully exit on broken pipe
std::process::exit(0);
Expand All @@ -23,6 +20,18 @@ pub fn print_to_stdout(args: std::fmt::Arguments) {
}
}

/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received.
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
pub fn print_to_stdout(args: std::fmt::Arguments) {
print_args_or_exit(args, std::io::stdout());
}

/// Print the input to stderr, and exit gracefully if `SIGPIPE` is received.
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
pub fn print_to_stderr(args: std::fmt::Arguments) {
print_args_or_exit(args, std::io::stderr());
}

/// Macro to print formatted output to stdout
#[macro_export]
macro_rules! print_to_stdout {
Expand All @@ -31,9 +40,26 @@ macro_rules! print_to_stdout {
};
}

/// Macro to print formatted output to stdout
#[macro_export]
macro_rules! println_to_stdout {
($($arg:tt)*) => {
noirc_errors::print_to_stdout(format_args!("{}\n", format!($($arg)*)))
};
}

/// Macro to print formatted output to stderr
#[macro_export]
macro_rules! print_to_stderr {
($($arg:tt)*) => {
noirc_errors::print_to_stderr(format_args!($($arg)*))
};
}

/// Macro to print formatted output to stderr
#[macro_export]
macro_rules! println_to_stderr {
($($arg:tt)*) => {
noirc_errors::print_to_stderr(format_args!("{}\n", format!($($arg)*)))
};
}
11 changes: 1 addition & 10 deletions compiler/noirc_evaluator/src/ssa/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,7 @@ impl<'local> SsaBuilder<'local> {
self.ssa.normalize_ids();
}

let print_ssa_pass = match &self.ssa_logging {
SsaLogging::None => false,
SsaLogging::All => true,
SsaLogging::Contains(strings) => strings.iter().any(|string| {
let string = string.to_lowercase();
let string = string.strip_prefix("after ").unwrap_or(&string);
let string = string.strip_suffix(':').unwrap_or(string);
msg.to_lowercase().contains(string)
}),
};
let print_ssa_pass = self.ssa_logging.matches(msg);

if print_ssa_pass {
println_to_stdout!("After {msg}:\n{}", self.ssa.print_with(self.files));
Expand Down
10 changes: 10 additions & 0 deletions compiler/noirc_evaluator/src/ssa/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,16 @@ impl Function {
pub fn has_data_bus_return_data(&self) -> bool {
self.dfg.data_bus.return_data.is_some()
}

/// Return the types of the function parameters.
pub fn parameter_types(&self) -> Vec<Type> {
vecmap(self.parameters(), |p| self.dfg.type_of_value(*p))
}

/// Return the types of the returned values, if there are any.
pub fn return_types(&self) -> Option<Vec<Type>> {
self.returns().map(|rs| vecmap(rs, |p| self.dfg.type_of_value(*p)))
}
}

impl Clone for Function {
Expand Down
16 changes: 16 additions & 0 deletions compiler/noirc_evaluator/src/ssa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ pub enum SsaLogging {
Contains(Vec<String>),
}

impl SsaLogging {
/// Check if an SSA pass should be printed.
pub fn matches(&self, msg: &str) -> bool {
match self {
SsaLogging::None => false,
SsaLogging::All => true,
SsaLogging::Contains(strings) => strings.iter().any(|string| {
let string = string.to_lowercase();
let string = string.strip_prefix("after ").unwrap_or(&string);
let string = string.strip_suffix(':').unwrap_or(string);
msg.to_lowercase().contains(string)
}),
}
}
}

#[derive(Debug, Clone)]
pub struct SsaEvaluatorOptions {
/// Emit debug information for the intermediate SSA IR
Expand Down
8 changes: 8 additions & 0 deletions examples/ssa_cli/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
set -eu

cd $(dirname $0)

# This file is used for Noir CI and is not required.

./transform_and_interpret_ssa.sh
22 changes: 22 additions & 0 deletions examples/ssa_cli/test.ssa
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
acir(inline) fn main f0 {
b0(v0: [[u8; 2]; 2], v1: u1, v2: u32):
jmpif v1 then: b1, else: b2
b1():
v3 = array_get v0, index v2 -> [u8; 2]
v4 = array_get v3, index v2 -> u8
call f1(v4)
jmp b2()
b2():
return
}
acir(inline) fn println f1 {
b0(v0: u8):
call f2(u1 1, v0)
return
}
brillig(inline) fn print_unconstrained f2 {
b0(v0: u1, v1: u8):
v20 = make_array b"{\"kind\":\"unsignedinteger\",\"width\":8}"
call print(v0, v1, v20, u1 0)
return
}
3 changes: 3 additions & 0 deletions examples/ssa_cli/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
v0 = [[1, 2], [3, 4]]
v1 = true
v2 = 0
11 changes: 11 additions & 0 deletions examples/ssa_cli/transform_and_interpret_ssa.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
set -eu

cd $(dirname $0)

# Sanity check that we can parse an SSA, pipe it through some transformations
# and interpret it with values from a TOML file.
cat ./test.ssa \
| noir-ssa transform --ssa-pass "step 1" \
| noir-ssa transform --ssa-pass "Dead Instruction Elimination" \
| noir-ssa interpret --input-path ./test.toml
4 changes: 2 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ci := if env("CI", "") == "true" {
"1"
} else {
"0"
}
}
use-cross := env("JUST_USE_CROSS", "")

# target information
Expand Down Expand Up @@ -113,7 +113,7 @@ fuzz-nightly: install-rust-tools
# Checks if there are any pending insta.rs snapshots and errors if any exist.
check-pending-snapshots:
#!/usr/bin/env bash
snapshots=$(find . -name *.snap.new)
snapshots=$(find . -name *.snap.new)
if [[ -n "$snapshots" ]]; then \
echo "Found pending snapshots:"
echo ""
Expand Down
2 changes: 1 addition & 1 deletion tooling/artifact_cli/src/bin/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn main() {
.init();

if let Err(e) = start_cli() {
eprintln!("{e:?}");
eprintln!("{e:#}");
std::process::exit(1);
}
}
2 changes: 1 addition & 1 deletion tooling/artifact_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod execute_cmd;

/// Parses a path and turns it into an absolute one by joining to the current directory,
/// then normalizes it.
fn parse_and_normalize_path(path: &str) -> eyre::Result<PathBuf> {
pub fn parse_and_normalize_path(path: &str) -> eyre::Result<PathBuf> {
use fm::NormalizePath;
let mut path: PathBuf = path.parse().map_err(|e| eyre!("failed to parse path: {e}"))?;
if !path.is_absolute() {
Expand Down
15 changes: 3 additions & 12 deletions tooling/nargo_cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use nargo_toml::{
ManifestError, NargoToml, PackageConfig, PackageMetadata, PackageSelection,
get_package_manifest, resolve_workspace_from_fixed_toml, resolve_workspace_from_toml,
};
use noir_artifact_cli::commands::parse_and_normalize_path;
use noirc_driver::{CrateName, NOIR_ARTIFACT_VERSION_STRING};
use std::{
collections::BTreeMap,
Expand Down Expand Up @@ -60,11 +61,11 @@ struct NargoCli {
#[derive(Args, Clone, Debug)]
pub struct NargoConfig {
// REMINDER: Also change this flag in the LSP test lens if renamed
#[arg(long, hide = true, global = true, default_value = "./", value_parser = parse_path)]
#[arg(long, hide = true, global = true, default_value = "./", value_parser = parse_and_normalize_path)]
program_dir: PathBuf,

/// Override the default target directory.
#[arg(long, hide = true, global = true, value_parser = parse_path)]
#[arg(long, hide = true, global = true, value_parser = parse_and_normalize_path)]
target_dir: Option<PathBuf>,
}

Expand Down Expand Up @@ -297,16 +298,6 @@ fn lock_workspace(
Ok(locks)
}

/// Parses a path and turns it into an absolute one by joining to the current directory.
fn parse_path(path: &str) -> Result<PathBuf, String> {
use fm::NormalizePath;
let mut path: PathBuf = path.parse().map_err(|e| format!("failed to parse path: {e}"))?;
if !path.is_absolute() {
path = std::env::current_dir().unwrap().join(path).normalize();
}
Ok(path)
}

#[cfg(test)]
mod tests {
use super::NargoCli;
Expand Down
Loading
Loading