Skip to content
Open
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
34 changes: 34 additions & 0 deletions compiler/noirc_evaluator/src/brillig/brillig_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ pub(crate) fn gen_brillig_for(

#[cfg(test)]
mod entry_point {
use acvm::acir::brillig::Opcode as BrilligOpcode;

use crate::{
assert_artifact_snapshot,
brillig::{
Expand Down Expand Up @@ -287,4 +289,36 @@ mod entry_point {
60: return
");
}

#[test]
fn unreachable_terminator_keeps_jump_targets_in_range() {
let src = "
brillig(inline) fn main f0 {
b0(v0: u32):
constrain v0 == u32 7
unreachable
}
";
let ssa = Ssa::from_str(src).unwrap();
let options = BrilligOptions::default();
let brillig = ssa.to_brillig(&options);

let args = vec![BrilligParameter::SingleAddr(32)];
let entry = gen_brillig_for(ssa.main(), &args, &brillig, &options).unwrap();

let len = entry.byte_code.len();
for (index, opcode) in entry.byte_code.iter().enumerate() {
let target = match opcode {
BrilligOpcode::Jump { location }
| BrilligOpcode::JumpIf { location, .. }
| BrilligOpcode::Call { location } => *location,
_ => continue,
};
assert!(
target < len,
"opcode {index} ({opcode:?}) targets {target}, \
which is out of range for a program of {len} opcodes"
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ impl<'block, Registers: RegisterAllocator> BrilligBlock<'block, Registers> {
self.brillig_context.codegen_return(&return_registers);
}
TerminatorInstruction::Unreachable { .. } => {
// If we assume this is unreachable code then there's nothing to do here
self.brillig_context.codegen_trap();
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions compiler/noirc_evaluator/src/brillig/brillig_gen/tests/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ fn brillig_global_array_not_coalesced_with_block_param() {
let brillig = ssa_to_brillig_artifacts(src);
let main = &brillig.ssa_function_to_brillig[&Id::test_new(0)];
// Key opcodes:
// 13: sp[2] = @68 — global g0 lives in global register @68, copied into sp[2] (param v3's slot)
// 15: return — returns sp[1]; global and param use separate allocations (not coalesced)
// 19: sp[2] = @68 — global g0 lives in global register @68, copied into sp[2] (param v3's slot)
// 21: return — returns sp[1]; global and param use separate allocations (not coalesced)
assert_artifact_snapshot!(main, @r"
fn main
0: sp[3] = @1
Expand All @@ -201,14 +201,16 @@ fn brillig_global_array_not_coalesced_with_block_param() {
8: @0 = sp[0]
9: sp[4] = sp[8]
10: jump if sp[4] to 0 // -> 12: f0/b1
11: jump to 0 // -> 17: f0/b2
11: jump to 0 // -> 19: f0/b2
12: sp[2] = const bool 1 // f0/b1
13: sp[3] = bool eq @69, sp[2]
14: jump if sp[3] to 0 // -> 17: f0/b1/1
15: sp[4] = const u32 0
16: trap @[@1; sp[4]]
17: sp[2] = @68 // f0/b1/1, f0/b2
18: jump to 0 // -> 19: f0/b3
19: return // f0/b3
17: sp[2] = const u32 0 // f0/b1/1
18: trap @[@1; sp[2]]
19: sp[2] = @68 // f0/b2
20: jump to 0 // -> 21: f0/b3
21: return // f0/b3
");
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<
self.enter_section(end_section);
}

/// Emits an unconditional trap with empty error data (no error information).
pub(crate) fn codegen_trap(&mut self) {
let error_data = self.make_usize_constant_instruction(0_usize.into()).map(|size| {
HeapVector { pointer: ReservedRegisters::free_memory_pointer(), size: size.address }
});
self.trap_instruction(*error_data);
}

/// Jump to a trap condition if `condition` is false.
/// The trap will include the given message as error data.
///
Expand All @@ -204,12 +212,7 @@ impl<F: AcirField + DebugToString, Registers: RegisterAllocator> BrilligContext<

// Special case: No error selector means completely empty error data
let Some(error_selector) = error_selector else {
let error_data =
ctx.make_usize_constant_instruction(0_usize.into()).map(|size| HeapVector {
pointer: ReservedRegisters::free_memory_pointer(),
size: size.address,
});
ctx.trap_instruction(*error_data);
ctx.codegen_trap();
return;
};

Expand Down
Loading