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 binary operations #8473

Merged
merged 6 commits into from
Sep 10, 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
2 changes: 1 addition & 1 deletion avm-transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Debug for AvmInstruction {
impl Default for AvmInstruction {
fn default() -> Self {
AvmInstruction {
opcode: AvmOpcode::ADD,
opcode: AvmOpcode::ADD_8,
// TODO(4266): default to Some(0), since all instructions have indirect flag except jumps
indirect: None,
tag: None,
Expand Down
78 changes: 52 additions & 26 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,33 @@
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
pub enum AvmOpcode {
// Compute
ADD,
SUB,
MUL,
DIV,
FDIV,
EQ,
LT,
LTE,
AND,
OR,
XOR,
ADD_8,
ADD_16,
SUB_8,
SUB_16,
MUL_8,
MUL_16,
DIV_8,
DIV_16,
FDIV_8,
FDIV_16,
EQ_8,
EQ_16,
LT_8,
LT_16,
LTE_8,
LTE_16,
AND_8,
AND_16,
OR_8,
OR_16,
XOR_8,
XOR_16,
NOT,
SHL,
SHR,
SHL_8,
SHL_16,
SHR_8,
SHR_16,
CAST,
// Execution environment
ADDRESS,
Expand Down Expand Up @@ -89,22 +102,35 @@ impl AvmOpcode {
match self {
// Compute
// Compute - Arithmetic
AvmOpcode::ADD => "ADD",
AvmOpcode::SUB => "SUB",
AvmOpcode::MUL => "MUL",
AvmOpcode::DIV => "DIV",
AvmOpcode::FDIV => "FDIV",
AvmOpcode::ADD_8 => "ADD_8",
AvmOpcode::ADD_16 => "ADD_16",
AvmOpcode::SUB_8 => "SUB_8",
AvmOpcode::SUB_16 => "SUB_16",
AvmOpcode::MUL_8 => "MUL_8",
AvmOpcode::MUL_16 => "MUL_16",
AvmOpcode::DIV_8 => "DIV_8",
AvmOpcode::DIV_16 => "DIV_16",
AvmOpcode::FDIV_8 => "FDIV_8",
AvmOpcode::FDIV_16 => "FDIV_16",
// Compute - Comparators
AvmOpcode::EQ => "EQ",
AvmOpcode::LT => "LT",
AvmOpcode::LTE => "LTE",
AvmOpcode::EQ_8 => "EQ_8",
AvmOpcode::EQ_16 => "EQ_16",
AvmOpcode::LT_8 => "LT_8",
AvmOpcode::LT_16 => "LT_16",
AvmOpcode::LTE_8 => "LTE_8",
AvmOpcode::LTE_16 => "LTE_16",
// Compute - Bitwise
AvmOpcode::AND => "AND",
AvmOpcode::OR => "OR",
AvmOpcode::XOR => "XOR",
AvmOpcode::AND_8 => "AND_8",
AvmOpcode::AND_16 => "AND_16",
AvmOpcode::OR_8 => "OR_8",
AvmOpcode::OR_16 => "OR_16",
AvmOpcode::XOR_8 => "XOR_8",
AvmOpcode::XOR_16 => "XOR_16",
AvmOpcode::NOT => "NOT",
AvmOpcode::SHL => "SHL",
AvmOpcode::SHR => "SHR",
AvmOpcode::SHL_8 => "SHL_8",
AvmOpcode::SHL_16 => "SHL_16",
AvmOpcode::SHR_8 => "SHR_8",
AvmOpcode::SHR_16 => "SHR_16",
// Compute - Type Conversions
AvmOpcode::CAST => "CAST",

Expand Down
155 changes: 126 additions & 29 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,65 @@ pub fn brillig_to_avm(
for brillig_instr in brillig_bytecode {
match brillig_instr {
BrilligOpcode::BinaryFieldOp { destination, op, lhs, rhs } => {
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();

assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryFieldOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryFieldOp::Add => AvmOpcode::ADD,
BinaryFieldOp::Sub => AvmOpcode::SUB,
BinaryFieldOp::Mul => AvmOpcode::MUL,
BinaryFieldOp::Div => AvmOpcode::FDIV,
BinaryFieldOp::IntegerDiv => AvmOpcode::DIV,
BinaryFieldOp::Equals => AvmOpcode::EQ,
BinaryFieldOp::LessThan => AvmOpcode::LT,
BinaryFieldOp::LessThanEquals => AvmOpcode::LTE,
BinaryFieldOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryFieldOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryFieldOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryFieldOp::Div => match bits_needed {
8 => AvmOpcode::FDIV_8,
16 => AvmOpcode::FDIV_16,
_ => unreachable!(),
},
BinaryFieldOp::IntegerDiv => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryFieldOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: if avm_opcode == AvmOpcode::FDIV { None } else { Some(AvmTypeTag::FIELD) },
tag: Some(AvmTypeTag::FIELD),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand All @@ -57,28 +98,84 @@ pub fn brillig_to_avm(
"BinaryIntOp bit size should be integral: {:?}",
brillig_instr
);
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();
assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryIntOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryIntOp::Add => AvmOpcode::ADD,
BinaryIntOp::Sub => AvmOpcode::SUB,
BinaryIntOp::Mul => AvmOpcode::MUL,
BinaryIntOp::Div => AvmOpcode::DIV,
BinaryIntOp::Equals => AvmOpcode::EQ,
BinaryIntOp::LessThan => AvmOpcode::LT,
BinaryIntOp::LessThanEquals => AvmOpcode::LTE,
BinaryIntOp::And => AvmOpcode::AND,
BinaryIntOp::Or => AvmOpcode::OR,
BinaryIntOp::Xor => AvmOpcode::XOR,
BinaryIntOp::Shl => AvmOpcode::SHL,
BinaryIntOp::Shr => AvmOpcode::SHR,
BinaryIntOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryIntOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryIntOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryIntOp::Div => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryIntOp::And => match bits_needed {
8 => AvmOpcode::AND_8,
16 => AvmOpcode::AND_16,
_ => unreachable!(),
},
BinaryIntOp::Or => match bits_needed {
8 => AvmOpcode::OR_8,
16 => AvmOpcode::OR_16,
_ => unreachable!(),
},
BinaryIntOp::Xor => match bits_needed {
8 => AvmOpcode::XOR_8,
16 => AvmOpcode::XOR_16,
_ => unreachable!(),
},
BinaryIntOp::Shl => match bits_needed {
8 => AvmOpcode::SHL_8,
16 => AvmOpcode::SHL_16,
_ => unreachable!(),
},
BinaryIntOp::Shr => match bits_needed {
8 => AvmOpcode::SHR_8,
16 => AvmOpcode::SHR_16,
_ => unreachable!(),
},
BinaryIntOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryIntOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryIntOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: Some(tag_from_bit_size(BitSize::Integer(*bit_size))),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand Down Expand Up @@ -214,9 +311,9 @@ pub fn brillig_to_avm(
// We are adding a MOV instruction that moves a value to itself.
// This should therefore not affect the program's execution.
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::MOV_8,
opcode: AvmOpcode::MOV_16,
indirect: Some(ALL_DIRECT),
operands: vec![AvmOperand::U32 { value: 0x18ca }, AvmOperand::U32 { value: 0x18ca }],
operands: vec![AvmOperand::U16 { value: 0x18ca }, AvmOperand::U16 { value: 0x18ca }],
..Default::default()
});

Expand Down
Loading
Loading