Skip to content

Commit e6260d7

Browse files
authored
feat(ssa): SSA CLI (#9826)
1 parent 548c6f7 commit e6260d7

File tree

21 files changed

+646
-33
lines changed

21 files changed

+646
-33
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Download noir-ssa
2+
description: Downloads the noir-ssa binary from an artifact and adds it to the path
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- name: Download noir-ssa binary
8+
uses: actions/download-artifact@v4
9+
with:
10+
name: noir-ssa
11+
path: ./noir-ssa
12+
13+
- name: Set noir-ssa on PATH
14+
shell: bash
15+
run: |
16+
noir_binary="${{ github.workspace }}/noir-ssa/noir-ssa"
17+
chmod +x $noir_binary
18+
echo "$(dirname $noir_binary)" >> $GITHUB_PATH

.github/workflows/test-js-packages.yml

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ jobs:
9999
cache-on-failure: true
100100
save-if: ${{ github.event_name != 'merge_group' }}
101101

102-
- name: Build noir-execute
102+
- name: Build artifact
103103
run: cargo build --package noir_artifact_cli --release
104104
env:
105105
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -111,6 +111,37 @@ jobs:
111111
path: ./target/release/noir-execute
112112
retention-days: 3
113113

114+
build-noir-ssa:
115+
runs-on: ubuntu-22.04
116+
timeout-minutes: 30
117+
permissions:
118+
contents: read
119+
120+
steps:
121+
- name: Checkout Noir repo
122+
uses: actions/checkout@v5
123+
124+
- name: Setup toolchain
125+
uses: dtolnay/[email protected]
126+
127+
- uses: Swatinem/rust-cache@v2
128+
with:
129+
key: x86_64-unknown-linux-gnu
130+
cache-on-failure: true
131+
save-if: ${{ github.event_name != 'merge_group' }}
132+
133+
- name: Build artifact
134+
run: cargo build --package noir_ssa_cli --release
135+
env:
136+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137+
138+
- name: Upload artifact
139+
uses: actions/upload-artifact@v4
140+
with:
141+
name: noir-ssa
142+
path: ./target/release/noir-ssa
143+
retention-days: 3
144+
114145
build-noirc-abi:
115146
runs-on: ubuntu-22.04
116147
timeout-minutes: 30
@@ -533,7 +564,7 @@ jobs:
533564
test-examples:
534565
name: Example scripts
535566
runs-on: ubuntu-24.04
536-
needs: [build-nargo, build-noir-execute, build-acvm-js, build-noirc-abi]
567+
needs: [build-nargo, build-noir-execute, build-noir-ssa, build-acvm-js, build-noirc-abi]
537568
timeout-minutes: 30
538569
permissions:
539570
contents: read
@@ -567,6 +598,9 @@ jobs:
567598
- name: Download noir-execute binary
568599
uses: ./.github/actions/download-noir-execute
569600

601+
- name: Download noir-ssa binary
602+
uses: ./.github/actions/download-noir-ssa
603+
570604
- name: Download acvm_js package artifact
571605
uses: actions/download-artifact@v4
572606
with:

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ members = [
4343
# Utility crates
4444
"utils/iter-extended",
4545

46+
"tooling/ssa_cli",
4647
"tooling/ssa_fuzzer",
4748
"tooling/ssa_fuzzer/fuzzer",
4849
"tooling/ssa_verification",
@@ -53,6 +54,7 @@ default-members = [
5354
"tooling/nargo_cli",
5455
"tooling/acvm_cli",
5556
"tooling/artifact_cli",
57+
"tooling/ssa_cli",
5658
"tooling/profiler",
5759
"tooling/inspector",
5860
]

compiler/noirc_errors/src/lib.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ pub use position::{Located, Location, Position};
1010
pub use reporter::{CustomDiagnostic, DiagnosticKind};
1111
use std::io::Write;
1212

13-
/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received.
14-
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
15-
pub fn print_to_stdout(args: std::fmt::Arguments) {
16-
let mut stdout = std::io::stdout();
17-
if let Err(e) = stdout.write_fmt(args) {
13+
pub fn print_args_or_exit<W: Write>(args: std::fmt::Arguments, mut out: W) {
14+
if let Err(e) = out.write_fmt(args) {
1815
if e.kind() == std::io::ErrorKind::BrokenPipe {
1916
// Gracefully exit on broken pipe
2017
std::process::exit(0);
@@ -24,6 +21,18 @@ pub fn print_to_stdout(args: std::fmt::Arguments) {
2421
}
2522
}
2623

24+
/// Print the input to stdout, and exit gracefully if `SIGPIPE` is received.
25+
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
26+
pub fn print_to_stdout(args: std::fmt::Arguments) {
27+
print_args_or_exit(args, std::io::stdout());
28+
}
29+
30+
/// Print the input to stderr, and exit gracefully if `SIGPIPE` is received.
31+
/// Rust ignores `SIGPIPE` by default, converting pipe errors into `ErrorKind::BrokenPipe`
32+
pub fn print_to_stderr(args: std::fmt::Arguments) {
33+
print_args_or_exit(args, std::io::stderr());
34+
}
35+
2736
/// Macro to print formatted output to stdout
2837
#[macro_export]
2938
macro_rules! print_to_stdout {
@@ -32,9 +41,26 @@ macro_rules! print_to_stdout {
3241
};
3342
}
3443

44+
/// Macro to print formatted output to stdout
3545
#[macro_export]
3646
macro_rules! println_to_stdout {
3747
($($arg:tt)*) => {
3848
noirc_errors::print_to_stdout(format_args!("{}\n", format!($($arg)*)))
3949
};
4050
}
51+
52+
/// Macro to print formatted output to stderr
53+
#[macro_export]
54+
macro_rules! print_to_stderr {
55+
($($arg:tt)*) => {
56+
noirc_errors::print_to_stderr(format_args!($($arg)*))
57+
};
58+
}
59+
60+
/// Macro to print formatted output to stderr
61+
#[macro_export]
62+
macro_rules! println_to_stderr {
63+
($($arg:tt)*) => {
64+
noirc_errors::print_to_stderr(format_args!("{}\n", format!($($arg)*)))
65+
};
66+
}

compiler/noirc_evaluator/src/ssa/builder.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,7 @@ impl<'local> SsaBuilder<'local> {
190190
self.ssa.normalize_ids();
191191
}
192192

193-
let print_ssa_pass = match &self.ssa_logging {
194-
SsaLogging::None => false,
195-
SsaLogging::All => true,
196-
SsaLogging::Contains(strings) => strings.iter().any(|string| {
197-
let string = string.to_lowercase();
198-
let string = string.strip_prefix("after ").unwrap_or(&string);
199-
let string = string.strip_suffix(':').unwrap_or(string);
200-
msg.to_lowercase().contains(string)
201-
}),
202-
};
193+
let print_ssa_pass = self.ssa_logging.matches(msg);
203194

204195
if print_ssa_pass {
205196
println_to_stdout!("After {msg}:\n{}", self.ssa.print_with(self.files));

compiler/noirc_evaluator/src/ssa/ir/function.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ impl Function {
239239
pub fn has_data_bus_return_data(&self) -> bool {
240240
self.dfg.data_bus.return_data.is_some()
241241
}
242+
243+
/// Return the types of the function parameters.
244+
pub fn parameter_types(&self) -> Vec<Type> {
245+
vecmap(self.parameters(), |p| self.dfg.type_of_value(*p))
246+
}
247+
248+
/// Return the types of the returned values, if there are any.
249+
pub fn return_types(&self) -> Option<Vec<Type>> {
250+
self.returns().map(|rs| vecmap(rs, |p| self.dfg.type_of_value(*p)))
251+
}
242252
}
243253

244254
impl Clone for Function {

compiler/noirc_evaluator/src/ssa/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ pub enum SsaLogging {
6060
Contains(Vec<String>),
6161
}
6262

63+
impl SsaLogging {
64+
/// Check if an SSA pass should be printed.
65+
pub fn matches(&self, msg: &str) -> bool {
66+
match self {
67+
SsaLogging::None => false,
68+
SsaLogging::All => true,
69+
SsaLogging::Contains(strings) => strings.iter().any(|string| {
70+
let string = string.to_lowercase();
71+
let string = string.strip_prefix("after ").unwrap_or(&string);
72+
let string = string.strip_suffix(':').unwrap_or(string);
73+
msg.to_lowercase().contains(string)
74+
}),
75+
}
76+
}
77+
}
78+
6379
#[derive(Debug, Clone)]
6480
pub struct SsaEvaluatorOptions {
6581
/// Emit debug information for the intermediate SSA IR

examples/ssa_cli/test.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
set -eu
3+
4+
cd $(dirname $0)
5+
6+
# This file is used for Noir CI and is not required.
7+
8+
./transform_and_interpret_ssa.sh

examples/ssa_cli/test.ssa

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
acir(inline) fn main f0 {
2+
b0(v0: [[u8; 2]; 2], v1: u1, v2: u32):
3+
jmpif v1 then: b1, else: b2
4+
b1():
5+
v3 = array_get v0, index v2 -> [u8; 2]
6+
v4 = array_get v3, index v2 -> u8
7+
call f1(v4)
8+
jmp b2()
9+
b2():
10+
return
11+
}
12+
acir(inline) fn println f1 {
13+
b0(v0: u8):
14+
call f2(u1 1, v0)
15+
return
16+
}
17+
brillig(inline) fn print_unconstrained f2 {
18+
b0(v0: u1, v1: u8):
19+
v20 = make_array b"{\"kind\":\"unsignedinteger\",\"width\":8}"
20+
call print(v0, v1, v20, u1 0)
21+
return
22+
}

0 commit comments

Comments
 (0)