fn emit_binary_op(bytecode: &mut Vec<u8>, operator: ir::BinaryOperator) {
let opcode = match operator {
ir::BinaryOperator::Add => 0x9E,
ir::BinaryOperator::Sub => 0x9F,
ir::BinaryOperator::Mul => 0xA0,
ir::BinaryOperator::Div => 0xA1,
ir::BinaryOperator::Mod => 0xA2,
ir::BinaryOperator::BitAnd => 0x91,
ir::BinaryOperator::BitOr => 0x92,
ir::BinaryOperator::BitXor => 0x93,
ir::BinaryOperator::Shl => 0xA8,
ir::BinaryOperator::Shr => 0xA9,
ir::BinaryOperator::Lt => 0xB5,
ir::BinaryOperator::Le => 0xB6,
ir::BinaryOperator::Gt => 0xB7,
ir::BinaryOperator::Ge => 0xB8,
ir::BinaryOperator::Eq => 0x97,
ir::BinaryOperator::Ne => 0x98,
};
bytecode.push(opcode);
}
fn push_literal_value(bytecode: &mut Vec<u8>, literal: &LiteralValue) {
match literal {
LiteralValue::Integer(value) => push_integer_bigint(bytecode, value),
LiteralValue::Boolean(true) => bytecode.push(0x08), LiteralValue::Boolean(false) => bytecode.push(0x09), LiteralValue::String(bytes) => push_data(bytecode, bytes),
LiteralValue::ByteArray(bytes) => push_data(bytecode, bytes),
LiteralValue::Address(bytes) => push_data(bytecode, bytes),
LiteralValue::Null => bytecode.push(0x0B),
}
}
fn push_integer_bigint(bytecode: &mut Vec<u8>, value: &BigInt) {
if value.is_zero() {
bytecode.push(0x10);
return;
}
if *value == BigInt::from(-1) {
bytecode.push(0x0F);
return;
}
if value.is_positive() {
if let Some(n) = value.to_u8() {
if n <= 16 {
bytecode.push(0x10 + n);
return;
}
}
}
if let Some(n) = value.to_i64() {
if (i8::MIN as i64..=i8::MAX as i64).contains(&n) {
bytecode.push(0x00); bytecode.push(n as i8 as u8);
return;
}
if (i16::MIN as i64..=i16::MAX as i64).contains(&n) {
bytecode.push(0x01); bytecode.extend_from_slice(&(n as i16).to_le_bytes());
return;
}
if (i32::MIN as i64..=i32::MAX as i64).contains(&n) {
bytecode.push(0x02); bytecode.extend_from_slice(&(n as i32).to_le_bytes());
return;
}
bytecode.push(0x03); bytecode.extend_from_slice(&n.to_le_bytes());
return;
}
let bytes = value.to_signed_bytes_le();
if bytes.len() <= 16 {
bytecode.push(0x04); let fill = if value.is_negative() { 0xFF } else { 0x00 };
let mut buf = [fill; 16];
buf[..bytes.len()].copy_from_slice(&bytes);
bytecode.extend_from_slice(&buf);
return;
}
if bytes.len() <= 32 {
bytecode.push(0x05); let fill = if value.is_negative() { 0xFF } else { 0x00 };
let mut buf = [fill; 32];
buf[..bytes.len()].copy_from_slice(&bytes);
bytecode.extend_from_slice(&buf);
return;
}
{
let two256: BigInt = BigInt::from(1) << 256u32;
let sign_min: BigInt = BigInt::from(1) << 255u32;
if value.is_positive() && *value < two256 && *value >= sign_min {
let twos: BigInt = value - &two256; let tb = twos.to_signed_bytes_le();
bytecode.push(0x05); let mut buf = [0xFFu8; 32]; buf[..tb.len()].copy_from_slice(&tb);
bytecode.extend_from_slice(&buf);
return;
}
}
push_data(bytecode, &bytes);
bytecode.push(0x10); bytecode.push(0x9E); }