Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(avm)!: variants for SET opcode #8441

Merged
merged 1 commit into from
Sep 9, 2024
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
5 changes: 5 additions & 0 deletions avm-transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::fmt::{self, Display};
use std::fmt::{Debug, Formatter};

use acvm::{AcirField, FieldElement};

use crate::opcodes::AvmOpcode;

/// Common values of the indirect instruction flag
Expand Down Expand Up @@ -110,6 +112,7 @@ pub enum AvmOperand {
U32 { value: u32 },
U64 { value: u64 },
U128 { value: u128 },
FF { value: FieldElement },
}

impl Display for AvmOperand {
Expand All @@ -120,6 +123,7 @@ impl Display for AvmOperand {
AvmOperand::U32 { value } => write!(f, " U32:{}", value),
AvmOperand::U64 { value } => write!(f, " U64:{}", value),
AvmOperand::U128 { value } => write!(f, " U128:{}", value),
AvmOperand::FF { value } => write!(f, " FF:{}", value),
}
}
}
Expand All @@ -132,6 +136,7 @@ impl AvmOperand {
AvmOperand::U32 { value } => value.to_be_bytes().to_vec(),
AvmOperand::U64 { value } => value.to_be_bytes().to_vec(),
AvmOperand::U128 { value } => value.to_be_bytes().to_vec(),
AvmOperand::FF { value } => value.to_be_bytes(),
}
}
}
14 changes: 12 additions & 2 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ pub enum AvmOpcode {
INTERNALCALL,
INTERNALRETURN,
// Memory
SET,
SET_8,
SET_16,
SET_32,
SET_64,
SET_128,
SET_FF,
MOV_8,
MOV_16,
CMOV,
Expand Down Expand Up @@ -129,7 +134,12 @@ impl AvmOpcode {
AvmOpcode::INTERNALCALL => "INTERNALCALL",
AvmOpcode::INTERNALRETURN => "INTERNALRETURN",
// Machine State - Memory
AvmOpcode::SET => "SET",
AvmOpcode::SET_8 => "SET_8",
AvmOpcode::SET_16 => "SET_16",
AvmOpcode::SET_32 => "SET_32",
AvmOpcode::SET_64 => "SET_64",
AvmOpcode::SET_128 => "SET_128",
AvmOpcode::SET_FF => "SET_FF",
AvmOpcode::MOV_8 => "MOV_8",
AvmOpcode::MOV_16 => "MOV_16",
AvmOpcode::CMOV => "CMOV",
Expand Down
51 changes: 21 additions & 30 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use acvm::acir::circuit::BrilligOpcodeLocation;
use acvm::brillig_vm::brillig::{
BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, MemoryAddress, ValueOrArray,
};
use acvm::{AcirField, FieldElement};
use acvm::FieldElement;
use noirc_errors::debug_info::DebugInfo;

use crate::bit_traits::bits_needed_for;
Expand Down Expand Up @@ -674,45 +674,38 @@ fn handle_const(
) {
let tag = tag_from_bit_size(*bit_size);
let dest = destination.to_usize() as u32;

if !matches!(tag, AvmTypeTag::FIELD) {
avm_instrs.push(generate_set_instruction(tag, dest, value.to_u128(), indirect));
} else {
// We can't fit a field in an instruction. This should've been handled in Brillig.
let field = value;
if field.num_bits() > 128 {
panic!("SET: Field value doesn't fit in 128 bits, that's not supported!");
}
avm_instrs.extend([
generate_set_instruction(AvmTypeTag::UINT128, dest, field.to_u128(), indirect),
generate_cast_instruction(dest, indirect, dest, indirect, AvmTypeTag::FIELD),
]);
}
avm_instrs.push(generate_set_instruction(tag, dest, value, indirect));
}

/// Generates an AVM SET instruction.
fn generate_set_instruction(
tag: AvmTypeTag,
dest: u32,
value: u128,
value: &FieldElement,
indirect: bool,
) -> AvmInstruction {
let bits_needed_val = bits_needed_for(value);
let bits_needed_mem = if bits_needed_val >= 16 { 16 } else { bits_needed_for(&dest) };
assert!(bits_needed_mem <= 16);
let bits_needed_opcode = bits_needed_val.max(bits_needed_mem);

let set_opcode = match bits_needed_opcode {
8 => AvmOpcode::SET_8,
16 => AvmOpcode::SET_16,
32 => AvmOpcode::SET_32,
64 => AvmOpcode::SET_64,
128 => AvmOpcode::SET_128,
254 => AvmOpcode::SET_FF,
_ => panic!("Invalid bits needed for opcode: {}", bits_needed_opcode),
};

AvmInstruction {
opcode: AvmOpcode::SET,
opcode: set_opcode,
indirect: if indirect { Some(ZEROTH_OPERAND_INDIRECT) } else { Some(ALL_DIRECT) },
tag: Some(tag),
operands: vec![
// const
match tag {
AvmTypeTag::UINT8 => AvmOperand::U8 { value: value as u8 },
AvmTypeTag::UINT16 => AvmOperand::U16 { value: value as u16 },
AvmTypeTag::UINT32 => AvmOperand::U32 { value: value as u32 },
AvmTypeTag::UINT64 => AvmOperand::U64 { value: value as u64 },
AvmTypeTag::UINT128 => AvmOperand::U128 { value },
_ => panic!("Invalid type tag {:?} for set", tag),
},
// dest offset
AvmOperand::U32 { value: dest },
make_operand(bits_needed_opcode, value),
make_operand(bits_needed_mem, &dest),
],
}
}
Expand Down Expand Up @@ -1137,8 +1130,6 @@ pub fn map_brillig_pcs_to_avm_pcs(brillig_bytecode: &[BrilligOpcode<FieldElement
pc_map[0] = 0; // first PC is always 0 as there are no instructions inserted by AVM at start
for i in 0..brillig_bytecode.len() - 1 {
let num_avm_instrs_for_this_brillig_instr = match &brillig_bytecode[i] {
BrilligOpcode::Const { bit_size: BitSize::Field, .. } => 2,
BrilligOpcode::IndirectConst { bit_size: BitSize::Field, .. } => 2,
BrilligOpcode::Cast { bit_size: BitSize::Integer(IntegerBitSize::U1), .. } => 3,
Comment on lines -1140 to 1133
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that we can remove these!

_ => 1,
};
Expand Down
16 changes: 9 additions & 7 deletions avm-transpiler/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use fxhash::FxHashMap as HashMap;

use acvm::acir::circuit::brillig::BrilligFunctionId;
use acvm::FieldElement;
use acvm::{AcirField, FieldElement};
use log::{debug, info, trace};

use acvm::acir::brillig::Opcode as BrilligOpcode;
Expand Down Expand Up @@ -91,13 +91,15 @@ pub fn dbg_print_avm_program(avm_program: &[AvmInstruction]) {
}
}

pub fn make_operand<T: Into<u128> + Copy>(bits: usize, value: &T) -> AvmOperand {
pub fn make_operand<T: Into<FieldElement> + Clone>(bits: usize, value: &T) -> AvmOperand {
let field: FieldElement = value.clone().into();
match bits {
8 => AvmOperand::U8 { value: Into::<u128>::into(*value) as u8 },
16 => AvmOperand::U16 { value: Into::<u128>::into(*value) as u16 },
32 => AvmOperand::U32 { value: Into::<u128>::into(*value) as u32 },
64 => AvmOperand::U64 { value: Into::<u128>::into(*value) as u64 },
128 => AvmOperand::U128 { value: Into::<u128>::into(*value) },
8 => AvmOperand::U8 { value: field.try_to_u32().unwrap() as u8 },
16 => AvmOperand::U16 { value: field.try_to_u32().unwrap() as u16 },
32 => AvmOperand::U32 { value: field.try_to_u32().unwrap() },
64 => AvmOperand::U64 { value: field.try_to_u64().unwrap() },
128 => AvmOperand::U128 { value: field.try_into_u128().unwrap() },
254 => AvmOperand::FF { value: field },
_ => panic!("Invalid operand size for bits: {}", bits),
}
}
Loading
Loading