Skip to content

Commit

Permalink
u256 more operations (#4904)
Browse files Browse the repository at this point in the history
## Description

This PR is part of #4794 and
implements more operators for u256:
- [x] sub
- [x] mul
- [x] div
- [x] comparisions
- [x] mod

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Vaivaswatha N <[email protected]>
  • Loading branch information
xunilrj and vaivaswatha authored Aug 7, 2023
1 parent 36da3cf commit 943c67c
Show file tree
Hide file tree
Showing 18 changed files with 866 additions and 41 deletions.
92 changes: 90 additions & 2 deletions sway-core/src/asm_generation/fuel/fuel_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
},
asm_lang::{
virtual_register::*, Label, Op, VirtualImmediate06, VirtualImmediate12, VirtualImmediate18,
VirtualOp,
VirtualOp, WideCmp,
},
decl_engine::DeclRefFunction,
metadata::MetadataManager,
Expand Down Expand Up @@ -250,10 +250,20 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
}
FuelVmInstruction::WideBinaryOp {
op,
result,
arg1,
arg2,
result,
} => self.compile_wide_binary_op(instr_val, op, arg1, arg2, result),
FuelVmInstruction::WideCmpOp { op, arg1, arg2 } => {
self.compile_wide_cmp_op(instr_val, op, arg1, arg2)
}
FuelVmInstruction::WideModularOp {
op,
result,
arg1,
arg2,
arg3,
} => self.compile_wide_modular_op(instr_val, op, result, arg1, arg2, arg3),
},
Instruction::GetElemPtr {
base,
Expand Down Expand Up @@ -503,6 +513,82 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
val2_reg,
VirtualImmediate06::wide_op(crate::asm_lang::WideOperations::Add, true),
),
BinaryOpKind::Sub => VirtualOp::WQOP(
result_reg,
val1_reg,
val2_reg,
VirtualImmediate06::wide_op(crate::asm_lang::WideOperations::Sub, true),
),
BinaryOpKind::Mul => VirtualOp::WQML(
result_reg,
val1_reg,
val2_reg,
VirtualImmediate06::wide_mul(true, true),
),
BinaryOpKind::Div => VirtualOp::WQDV(
result_reg,
val1_reg,
val2_reg,
VirtualImmediate06::wide_div(true),
),
_ => todo!(),
};

self.cur_bytecode.push(Op {
opcode: Either::Left(opcode),
comment: String::new(),
owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
});

Ok(())
}

fn compile_wide_modular_op(
&mut self,
instr_val: &Value,
op: &BinaryOpKind,
result: &Value,
arg1: &Value,
arg2: &Value,
arg3: &Value,
) -> Result<(), CompileError> {
let result_reg = self.value_to_register(result)?;
let val1_reg = self.value_to_register(arg1)?;
let val2_reg = self.value_to_register(arg2)?;
let val3_reg = self.value_to_register(arg3)?;

let opcode = match op {
BinaryOpKind::Mod => VirtualOp::WQAM(result_reg, val1_reg, val2_reg, val3_reg),
_ => todo!(),
};

self.cur_bytecode.push(Op {
opcode: Either::Left(opcode),
comment: String::new(),
owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
});

Ok(())
}

fn compile_wide_cmp_op(
&mut self,
instr_val: &Value,
op: &Predicate,
arg1: &Value,
arg2: &Value,
) -> Result<(), CompileError> {
let res_reg = self.reg_seqr.next();
let val1_reg = self.value_to_register(arg1)?;
let val2_reg = self.value_to_register(arg2)?;

let opcode = match op {
Predicate::Equal => VirtualOp::WQCM(
res_reg.clone(),
val1_reg,
val2_reg,
VirtualImmediate06::wide_cmp(WideCmp::Equality, true),
),
_ => todo!(),
};

Expand All @@ -512,6 +598,8 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
});

self.reg_map.insert(*instr_val, res_reg);

Ok(())
}

Expand Down
44 changes: 44 additions & 0 deletions sway-core/src/asm_lang/allocated_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,30 @@ pub(crate) enum AllocatedOpcode {
AllocatedRegister,
VirtualImmediate06,
),
WQML(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
VirtualImmediate06,
),
WQDV(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
VirtualImmediate06,
),
WQCM(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
VirtualImmediate06,
),
WQAM(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),

/* Conrol Flow Instructions */
JMP(AllocatedRegister),
Expand Down Expand Up @@ -250,6 +274,10 @@ impl AllocatedOpcode {
XOR(r1, _r2, _r3) => vec![r1],
XORI(r1, _r2, _i) => vec![r1],
WQOP(_, _, _, _) => vec![],
WQML(_, _, _, _) => vec![],
WQDV(_, _, _, _) => vec![],
WQCM(r1, _, _, _) => vec![r1],
WQAM(_, _, _, _) => vec![],

/* Control Flow Instructions */
JMP(_r1) => vec![],
Expand Down Expand Up @@ -364,6 +392,10 @@ impl fmt::Display for AllocatedOpcode {
XOR(a, b, c) => write!(fmtr, "xor {a} {b} {c}"),
XORI(a, b, c) => write!(fmtr, "xori {a} {b} {c}"),
WQOP(a, b, c, d) => write!(fmtr, "wqop {a} {b} {c} {d}"),
WQML(a, b, c, d) => write!(fmtr, "wqml {a} {b} {c} {d}"),
WQDV(a, b, c, d) => write!(fmtr, "wqdv {a} {b} {c} {d}"),
WQCM(a, b, c, d) => write!(fmtr, "wqcm {a} {b} {c} {d}"),
WQAM(a, b, c, d) => write!(fmtr, "wqam {a} {b} {c} {d}"),

/* Control Flow Instructions */
JMP(a) => write!(fmtr, "jmp {a}"),
Expand Down Expand Up @@ -511,6 +543,18 @@ impl AllocatedOp {
WQOP(a, b, c, d) => {
op::WQOP::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.value.into()).into()
}
WQML(a, b, c, d) => {
op::WQML::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.value.into()).into()
}
WQDV(a, b, c, d) => {
op::WQDV::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.value.into()).into()
}
WQCM(a, b, c, d) => {
op::WQCM::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.value.into()).into()
}
WQAM(a, b, c, d) => {
op::WQAM::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}

/* Control Flow Instructions */
JMP(a) => op::JMP::new(a.to_reg_id()).into(),
Expand Down
4 changes: 4 additions & 0 deletions sway-core/src/asm_lang/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,10 @@ impl fmt::Display for VirtualOp {
XOR(a, b, c) => write!(fmtr, "xor {a} {b} {c}"),
XORI(a, b, c) => write!(fmtr, "xori {a} {b} {c}"),
WQOP(a, b, c, d) => write!(fmtr, "wqop {a} {b} {c} {d}"),
WQML(a, b, c, d) => write!(fmtr, "wqml {a} {b} {c} {d}"),
WQDV(a, b, c, d) => write!(fmtr, "wqdv {a} {b} {c} {d}"),
WQCM(a, b, c, d) => write!(fmtr, "wqcm {a} {b} {c} {d}"),
WQAM(a, b, c, d) => write!(fmtr, "wqam {a} {b} {c} {d}"),

/* Control Flow Instructions */
JMP(a) => write!(fmtr, "jmp {a}"),
Expand Down
23 changes: 23 additions & 0 deletions sway-core/src/asm_lang/virtual_immediate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ use std::fmt;
#[repr(u8)]
pub enum WideOperations {
Add = 0,
Sub = 1,
}

#[repr(u8)]
pub enum WideCmp {
Equality = 0,
}

/// 6-bit immediate value type
Expand Down Expand Up @@ -47,6 +53,23 @@ impl VirtualImmediate06 {
value: (op as u8) | if rhs_indirect { 32u8 } else { 0 },
}
}

pub fn wide_cmp(op: WideCmp, rhs_indirect: bool) -> VirtualImmediate06 {
VirtualImmediate06 {
value: (op as u8) | if rhs_indirect { 32u8 } else { 0 },
}
}

pub fn wide_mul(lhs_indirect: bool, rhs_indirect: bool) -> VirtualImmediate06 {
let lhs = if lhs_indirect { 16u8 } else { 0 };
let rhs = if rhs_indirect { 32u8 } else { 0 };
VirtualImmediate06 { value: lhs | rhs }
}

pub fn wide_div(rhs_indirect: bool) -> VirtualImmediate06 {
let rhs = if rhs_indirect { 32u8 } else { 0 };
VirtualImmediate06 { value: rhs }
}
}

impl fmt::Display for VirtualImmediate06 {
Expand Down
84 changes: 84 additions & 0 deletions sway-core/src/asm_lang/virtual_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ pub(crate) enum VirtualOp {
VirtualRegister,
VirtualImmediate06,
),
WQML(
VirtualRegister,
VirtualRegister,
VirtualRegister,
VirtualImmediate06,
),
WQDV(
VirtualRegister,
VirtualRegister,
VirtualRegister,
VirtualImmediate06,
),
WQCM(
VirtualRegister,
VirtualRegister,
VirtualRegister,
VirtualImmediate06,
),
WQAM(
VirtualRegister,
VirtualRegister,
VirtualRegister,
VirtualRegister,
),

/* Control Flow Instructions */
JMP(VirtualRegister),
Expand Down Expand Up @@ -214,6 +238,10 @@ impl VirtualOp {
XOR(r1, r2, r3) => vec![r1, r2, r3],
XORI(r1, r2, _i) => vec![r1, r2],
WQOP(r1, r2, r3, _) => vec![r1, r2, r3],
WQML(r1, r2, r3, _) => vec![r1, r2, r3],
WQDV(r1, r2, r3, _) => vec![r1, r2, r3],
WQCM(r1, r2, r3, _) => vec![r1, r2, r3],
WQAM(r1, r2, r3, r4) => vec![r1, r2, r3, r4],

/* Control Flow Instructions */
JMP(r1) => vec![r1],
Expand Down Expand Up @@ -324,6 +352,10 @@ impl VirtualOp {
XOR(_r1, r2, r3) => vec![r2, r3],
XORI(_r1, r2, _i) => vec![r2],
WQOP(r1, r2, r3, _) => vec![r1, r2, r3],
WQML(r1, r2, r3, _) => vec![r1, r2, r3],
WQDV(r1, r2, r3, _) => vec![r1, r2, r3],
WQCM(_, r2, r3, _) => vec![r2, r3],
WQAM(_, r2, r3, r4) => vec![r2, r3, r4],

/* Control Flow Instructions */
JMP(r1) => vec![r1],
Expand Down Expand Up @@ -434,6 +466,10 @@ impl VirtualOp {
XOR(r1, _r2, _r3) => vec![r1],
XORI(r1, _r2, _i) => vec![r1],
WQOP(_, _, _, _) => vec![],
WQML(_, _, _, _) => vec![],
WQDV(_, _, _, _) => vec![],
WQCM(r1, _, _, _) => vec![r1],
WQAM(r1, _, _, _) => vec![r1],

/* Control Flow Instructions */
JMP(_r1) => vec![],
Expand Down Expand Up @@ -685,6 +721,30 @@ impl VirtualOp {
update_reg(reg_to_reg_map, r3),
i.clone(),
),
WQML(r1, r2, r3, i) => Self::WQML(
update_reg(reg_to_reg_map, r1),
update_reg(reg_to_reg_map, r2),
update_reg(reg_to_reg_map, r3),
i.clone(),
),
WQDV(r1, r2, r3, i) => Self::WQDV(
update_reg(reg_to_reg_map, r1),
update_reg(reg_to_reg_map, r2),
update_reg(reg_to_reg_map, r3),
i.clone(),
),
WQCM(r1, r2, r3, i) => Self::WQCM(
update_reg(reg_to_reg_map, r1),
update_reg(reg_to_reg_map, r2),
update_reg(reg_to_reg_map, r3),
i.clone(),
),
WQAM(r1, r2, r3, r4) => Self::WQAM(
update_reg(reg_to_reg_map, r1),
update_reg(reg_to_reg_map, r2),
update_reg(reg_to_reg_map, r3),
update_reg(reg_to_reg_map, r4),
),

/* Control Flow Instructions */
JMP(r1) => Self::JMP(update_reg(reg_to_reg_map, r1)),
Expand Down Expand Up @@ -1109,6 +1169,30 @@ impl VirtualOp {
map_reg(&mapping, reg3),
imm.clone(),
),
WQML(reg1, reg2, reg3, imm) => AllocatedOpcode::WQML(
map_reg(&mapping, reg1),
map_reg(&mapping, reg2),
map_reg(&mapping, reg3),
imm.clone(),
),
WQDV(reg1, reg2, reg3, imm) => AllocatedOpcode::WQDV(
map_reg(&mapping, reg1),
map_reg(&mapping, reg2),
map_reg(&mapping, reg3),
imm.clone(),
),
WQCM(reg1, reg2, reg3, imm) => AllocatedOpcode::WQCM(
map_reg(&mapping, reg1),
map_reg(&mapping, reg2),
map_reg(&mapping, reg3),
imm.clone(),
),
WQAM(reg1, reg2, reg3, reg4) => AllocatedOpcode::WQAM(
map_reg(&mapping, reg1),
map_reg(&mapping, reg2),
map_reg(&mapping, reg3),
map_reg(&mapping, reg4),
),

/* Control Flow Instructions */
JMP(reg1) => AllocatedOpcode::JMP(map_reg(&mapping, reg1)),
Expand Down
Loading

0 comments on commit 943c67c

Please sign in to comment.