Skip to content

Commit

Permalink
feat: Stop with HeapVector (#9810)
Browse files Browse the repository at this point in the history
Updates the Brillig stop opcode to return a HeapVector (pointer +
dynamic size). Also changes the transpiler, simulator and witness gen of
the AVM to support it.
  • Loading branch information
sirasistant authored Nov 12, 2024
1 parent 0ed5c1d commit 52ae4e1
Show file tree
Hide file tree
Showing 41 changed files with 915 additions and 540 deletions.
59 changes: 34 additions & 25 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,16 +306,12 @@ pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode<FieldElement>]) -> (Vec<
}
BrilligOpcode::Return {} => avm_instrs
.push(AvmInstruction { opcode: AvmOpcode::INTERNALRETURN, ..Default::default() }),
BrilligOpcode::Stop { return_data_offset, return_data_size } => {
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::RETURN,
indirect: Some(AddressingModeBuilder::default().build()),
operands: vec![
AvmOperand::U16 { value: *return_data_offset as u16 },
AvmOperand::U16 { value: *return_data_size as u16 },
],
..Default::default()
});
BrilligOpcode::Stop { return_data } => {
generate_return_instruction(
&mut avm_instrs,
&return_data.pointer,
&return_data.size,
);
}
BrilligOpcode::Trap { revert_data } => {
generate_revert_instruction(
Expand Down Expand Up @@ -960,6 +956,28 @@ fn generate_revert_instruction(
});
}

/// Generates an AVM RETURN instruction.
fn generate_return_instruction(
avm_instrs: &mut Vec<AvmInstruction>,
return_data_pointer: &MemoryAddress,
return_data_size_offset: &MemoryAddress,
) {
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::RETURN,
indirect: Some(
AddressingModeBuilder::default()
.indirect_operand(return_data_pointer)
.direct_operand(return_data_size_offset)
.build(),
),
operands: vec![
AvmOperand::U16 { value: return_data_pointer.to_usize() as u16 },
AvmOperand::U16 { value: return_data_size_offset.to_usize() as u16 },
],
..Default::default()
});
}

/// Generates an AVM MOV instruction.
fn generate_mov_instruction(
indirect: Option<AvmOperand>,
Expand Down Expand Up @@ -1323,25 +1341,16 @@ fn handle_return(
destinations: &Vec<ValueOrArray>,
inputs: &Vec<ValueOrArray>,
) {
assert!(inputs.len() == 1);
assert!(inputs.len() == 2);
assert!(destinations.len() == 0);

let (return_data_offset, return_data_size) = match inputs[0] {
ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer, size as u32),
_ => panic!("Return instruction's args input should be a HeapArray"),
// First arg is the size, which is ignored because it's redundant.
let (return_data_offset, return_data_size) = match inputs[1] {
ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer, size),
_ => panic!("Revert instruction's args input should be a HeapVector"),
};

avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::RETURN,
indirect: Some(
AddressingModeBuilder::default().indirect_operand(&return_data_offset).build(),
),
operands: vec![
AvmOperand::U16 { value: return_data_offset.to_usize() as u16 },
AvmOperand::U16 { value: return_data_size as u16 },
],
..Default::default()
});
generate_return_instruction(avm_instrs, &return_data_offset, &return_data_size);
}

// #[oracle(avmOpcodeRevert)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class AcirAvmRecursionConstraint : public ::testing::Test {
trace_builder.op_add(0, 1, 2, 3);
trace_builder.op_sub(0, 3, 2, 3);
trace_builder.op_mul(0, 1, 1, 3);
trace_builder.op_return(0, 0, 0);
trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32);
trace_builder.op_return(0, 0, 100);
auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups

avm_trace::inject_end_gas_values(public_inputs, trace);
Expand Down
14 changes: 4 additions & 10 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,7 @@ struct BrilligOpcode {
};

struct Stop {
uint64_t return_data_offset;
uint64_t return_data_size;
Program::HeapVector return_data;

friend bool operator==(const Stop&, const Stop&);
std::vector<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -6401,10 +6400,7 @@ namespace Program {

inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs)
{
if (!(lhs.return_data_offset == rhs.return_data_offset)) {
return false;
}
if (!(lhs.return_data_size == rhs.return_data_size)) {
if (!(lhs.return_data == rhs.return_data)) {
return false;
}
return true;
Expand Down Expand Up @@ -6434,8 +6430,7 @@ template <typename Serializer>
void serde::Serializable<Program::BrilligOpcode::Stop>::serialize(const Program::BrilligOpcode::Stop& obj,
Serializer& serializer)
{
serde::Serializable<decltype(obj.return_data_offset)>::serialize(obj.return_data_offset, serializer);
serde::Serializable<decltype(obj.return_data_size)>::serialize(obj.return_data_size, serializer);
serde::Serializable<decltype(obj.return_data)>::serialize(obj.return_data, serializer);
}

template <>
Expand All @@ -6444,8 +6439,7 @@ Program::BrilligOpcode::Stop serde::Deserializable<Program::BrilligOpcode::Stop>
Deserializer& deserializer)
{
Program::BrilligOpcode::Stop obj;
obj.return_data_offset = serde::Deserializable<decltype(obj.return_data_offset)>::deserialize(deserializer);
obj.return_data_size = serde::Deserializable<decltype(obj.return_data_size)>::deserialize(deserializer);
obj.return_data = serde::Deserializable<decltype(obj.return_data)>::deserialize(deserializer);
return obj;
}

Expand Down
Loading

0 comments on commit 52ae4e1

Please sign in to comment.