Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Sep 9, 2024
1 parent 5042aab commit 8c58258
Show file tree
Hide file tree
Showing 30 changed files with 720 additions and 790 deletions.
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,
_ => 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

0 comments on commit 8c58258

Please sign in to comment.