Skip to content
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
85 changes: 73 additions & 12 deletions compiler/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ pub struct ProgramOptions {

#[arg(long, action = clap::ArgAction::SetTrue)]
pub skip_vm: bool,

/// Print absolute paths in VM stack traces and WASM debug info instead of paths relative to the current directory.
#[arg(long, action = clap::ArgAction::SetTrue)]
pub absolute_paths: bool,

/// Include source metadata in bytecode and WASM artifacts.
#[arg(long, global = true, action = clap::ArgAction::SetTrue)]
pub include_debug_info: bool,
}

#[derive(Clone, Debug, Subcommand)]
Expand Down Expand Up @@ -84,12 +92,18 @@ fn main() -> ExitCode {
r1cs_output,
binary_output,
draw_graphs,
}) => run_compile(path, r1cs_output, binary_output, *draw_graphs),
}) => run_compile(
path,
r1cs_output,
binary_output,
*draw_graphs,
args.include_debug_info,
),
None => run(&args),
};

result.unwrap_or_else(|err| {
eprintln!("Error Encountered: {err:?}");
eprintln!("Error Encountered: {err}");
ExitCode::FAILURE
})
}
Expand All @@ -113,11 +127,18 @@ pub fn run_compile(
r1cs_output: &PathBuf,
binary_output: &PathBuf,
draw_graphs: bool,
include_debug_info: bool,
) -> Result<ExitCode, Error> {
info!(message = %"Compiling Noir project", root = ?path, r1cs_output = ?r1cs_output, binary_output = ?binary_output);

let (mut driver, r1cs) = compile_to_r1cs(path.clone(), draw_graphs)?;
let binary = api::compile_bytecode(&mut driver, CodeGenOptions::default())?;
let binary = api::compile_bytecode(
&mut driver,
CodeGenOptions {
include_debug_info,
..CodeGenOptions::default()
},
)?;

// Ensure output directories exist
if let Some(parent) = r1cs_output.parent() {
Expand Down Expand Up @@ -157,6 +178,15 @@ pub fn run_compile(
/// `main` function of the application.
pub fn run(args: &ProgramOptions) -> Result<ExitCode, Error> {
let (mut driver, r1cs) = compile_to_r1cs(args.root.clone(), args.draw_graphs)?;
let codegen_options = CodeGenOptions {
include_debug_info: args.include_debug_info,
..CodeGenOptions::default()
};
let source_path_root = if args.absolute_paths {
None
} else {
Some(std::env::current_dir()?.canonicalize()?)
};
if args.pprint_r1cs {
use std::io::Write;
let mut r1cs_file =
Expand All @@ -171,7 +201,14 @@ pub fn run(args: &ProgramOptions) -> Result<ExitCode, Error> {
let wasm_path = driver.get_debug_output_dir().join("program.wasm");
info!(message = %"Generating WebAssembly", path = %wasm_path.display());
let runtime_lib = mavros_compiler::wasm_runtime::locate_or_build();
Some((wasm_path, WasmCompileOpts::release(runtime_lib)))
let mut opts = WasmCompileOpts::release(runtime_lib);
if let Some(root) = &source_path_root {
opts = opts.with_debug_path_root(root);
}
if args.include_debug_info {
opts = opts.with_debug_info();
}
Some((wasm_path, opts))
} else {
None
};
Expand All @@ -181,12 +218,7 @@ pub fn run(args: &ProgramOptions) -> Result<ExitCode, Error> {
}

driver
.compile_llvm_targets(
args.emit_llvm,
&r1cs,
wasm_config,
CodeGenOptions::default(),
)
.compile_llvm_targets(args.emit_llvm, &r1cs, wasm_config, codegen_options)
.unwrap();
}

Expand All @@ -197,9 +229,15 @@ pub fn run(args: &ProgramOptions) -> Result<ExitCode, Error> {
}

let params = api::read_prover_inputs(driver.package_root(), driver.abi())?;
let mut binary = api::compile_bytecode(&mut driver, CodeGenOptions::default())?;
let mut binary = api::compile_bytecode(&mut driver, codegen_options)?;

let witgen_result = api::run_witgen_from_binary(&mut binary, &r1cs, &params)?;
let witgen_result =
api::run_witgen_from_binary(&mut binary, &r1cs, &params).map_err(|mut error| {
if let Some(root) = &source_path_root {
error.relativize_source_paths(root);
}
error
})?;

let correct = api::check_witgen(&r1cs, &witgen_result);
if !correct {
Expand Down Expand Up @@ -331,3 +369,26 @@ fn parse_path(path: &str) -> Result<PathBuf, String> {
}
Ok(path)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn debug_info_is_excluded_by_default_with_path_and_metadata_opt_ins() {
let relative = ProgramOptions::try_parse_from(["mavros"]).unwrap();
assert!(!relative.absolute_paths);
assert!(!relative.include_debug_info);

let absolute =
ProgramOptions::try_parse_from(["mavros", "--absolute-paths", "--include-debug-info"])
.unwrap();
assert!(absolute.absolute_paths);
assert!(absolute.include_debug_info);

let compile =
ProgramOptions::try_parse_from(["mavros", "compile", ".", "--include-debug-info"])
.unwrap();
assert!(compile.include_debug_info);
}
}
24 changes: 18 additions & 6 deletions compiler/src/bin/test_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ use mavros_wasm_layout::{
};
use noirc_abi::input_parser::Format;
use rand::SeedableRng;
use wasmtime::{Engine, Linker, Memory, Module, Store};
use wasmtime::{Config, Engine, Linker, Memory, Module, Store, WasmBacktraceDetails};

fn wasm_engine() -> wasmtime::Result<Engine> {
let mut config = Config::new();
config.wasm_backtrace_details(WasmBacktraceDetails::Enable);
Engine::new(&config)
}

fn main() {
let args: Vec<String> = env::args().collect();
Expand Down Expand Up @@ -139,6 +145,7 @@ fn emit(line: &str) {
fn run_single(root: PathBuf, expect_failure: bool) {
let checking_codegen = CodeGenOptions {
check_constraints: true,
..CodeGenOptions::default()
};

// 1. Compile
Expand Down Expand Up @@ -217,6 +224,8 @@ fn run_single(root: PathBuf, expect_failure: bool) {
}
});

let source_path_root = driver.package_root().to_path_buf();

// Load inputs (needed for witgen run)
let ordered_params = load_inputs(&driver.package_root().join("Prover.toml"), &driver);

Expand All @@ -230,7 +239,8 @@ fn run_single(root: PathBuf, expect_failure: bool) {
emit("END:WITGEN_RUN:ok");
Some(result)
}
Err(e) => {
Err(mut e) => {
e.relativize_source_paths(&source_path_root);
eprintln!("witgen run error: {e}");
emit("END:WITGEN_RUN:fail");
None
Expand Down Expand Up @@ -288,7 +298,8 @@ fn run_single(root: PathBuf, expect_failure: bool) {
emit("END:AD_RUN:ok");
Some((ad_coeffs, ad_a, ad_b, ad_c, ad_instrumenter))
}
Err(e) => {
Err(mut e) => {
e.relativize_source_paths(&source_path_root);
eprintln!("AD run error: {e}");
emit("END:AD_RUN:fail");
None
Expand Down Expand Up @@ -324,7 +335,8 @@ fn run_single(root: PathBuf, expect_failure: bool) {
emit("START:WASM_COMPILE");
let tmpdir = tempfile::tempdir().ok()?;
let wasm_path = tmpdir.keep().join("program.wasm");
let wasm_opts = WasmCompileOpts::fast(wasm_runtime::locate_or_build());
let wasm_opts = WasmCompileOpts::fast(wasm_runtime::locate_or_build())
.with_debug_path_root(&source_path_root);
match driver.compile_llvm_targets(
false,
r1cs,
Expand Down Expand Up @@ -567,7 +579,7 @@ fn run_wasm(
vm_struct_size + witness_bytes + 3 * constraint_bytes + input_bytes + table_info_bytes;

// Create wasmtime engine and store
let engine = Engine::default();
let engine = wasm_engine()?;
let mut store = Store::new(&engine, ());

// Load the WASM module
Expand Down Expand Up @@ -880,7 +892,7 @@ fn run_ad_wasm(
let coeffs_bytes = (constraint_count * FIELD_SIZE) as u32;
let our_data_size = vm_struct_size + da_bytes + db_bytes + dc_bytes + coeffs_bytes;

let engine = Engine::default();
let engine = wasm_engine()?;
let mut store = Store::new(&engine, ());

let wasm_bytes = fs::read(wasm_path)?;
Expand Down
41 changes: 36 additions & 5 deletions compiler/src/compiler/codegen/bytecode/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
},
},
ssa::{
BlockId, FunctionId, Instruction, Terminator, ValueId,
BlockId, FunctionId, Instruction, SourceLocation, Terminator, ValueId,
hlssa::{
self, BinaryArithOpKind, CmpKind, DMatrix, Endianness, HLBlock, HLFunction, HLSSA,
HLSSAConstantsSnapshot, LookupTarget, MAX_SUPPORTED_SIGNED_BITS, Radix, RefCountOp,
Expand All @@ -29,6 +29,14 @@ use crate::{
vm::{self, bytecode},
};

fn vm_source_location(location: &SourceLocation) -> bytecode::SourceLocation {
bytecode::SourceLocation::new(
location.file.to_string(),
location.start.line,
location.start.column,
)
}

/// Materialize every constant `ValueId` referenced by `function` into the function's frame at
/// entry.
///
Expand Down Expand Up @@ -217,7 +225,12 @@ impl CodeGen {
) -> bytecode::Function {
let mut layouter = FrameLayouter::new();
let entry = function.get_entry();
let mut emitter = EmitterState::new();
let fallback_location = function
.get_entry()
.first_location()
.cloned()
.unwrap_or_else(|| SourceLocation::synthetic(function.get_name()));
let mut emitter = EmitterState::new(vm_source_location(&fallback_location));

// Entry block params need to be allocated at the beginning of the frame (after return
// address and return data pointer)
Expand Down Expand Up @@ -344,12 +357,13 @@ impl CodeGen {
name: function.get_name().to_string(),
frame_size: layouter.next_free,
code: emitter.code,
source_locations: emitter.source_locations,
}
}

fn run_block_body(
&self,
_function: &HLFunction,
function: &HLFunction,
block_id: BlockId,
block: &HLBlock,
type_info: &FunctionTypeInfo,
Expand All @@ -358,8 +372,15 @@ impl CodeGen {
emitter: &mut EmitterState,
global_layouter: &GlobalFrameLayouter,
) {
let block_location = block
.first_location()
.or_else(|| function.get_entry().first_location())
.cloned()
.unwrap_or_else(|| SourceLocation::synthetic(function.get_name()));
emitter.set_source_location(vm_source_location(&block_location));
emitter.enter_block(block_id);
for instruction in block.get_instructions() {
for (instruction, source_location) in block.get_instructions_with_source_locations() {
emitter.set_source_location(vm_source_location(source_location));
match instruction {
hlssa::OpCode::BinaryArithOp {
kind: BinaryArithOpKind::Add,
Expand Down Expand Up @@ -1652,21 +1673,31 @@ impl CodeGen {

struct EmitterState {
code: Vec<bytecode::OpCode>,
source_locations: Vec<bytecode::SourceLocation>,
current_source_location: bytecode::SourceLocation,
block_entrances: HashMap<BlockId, usize>,
block_exits: HashMap<BlockId, usize>,
}

impl EmitterState {
fn new() -> Self {
fn new(current_source_location: bytecode::SourceLocation) -> Self {
Self {
code: Vec::new(),
source_locations: Vec::new(),
current_source_location,
block_entrances: HashMap::default(),
block_exits: HashMap::default(),
}
}

fn push_op(&mut self, op: bytecode::OpCode) {
self.code.push(op);
self.source_locations
.push(self.current_source_location.clone());
}

fn set_source_location(&mut self, source_location: bytecode::SourceLocation) {
self.current_source_location = source_location;
}

fn enter_block(&mut self, block: BlockId) {
Expand Down
Loading
Loading