Skip to content

Commit

Permalink
binary ops for u256
Browse files Browse the repository at this point in the history
  • Loading branch information
xunilrj committed Jul 21, 2023
1 parent afdd1ae commit bf3db1f
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 367 deletions.
2 changes: 1 addition & 1 deletion sway-core/src/abi_generation/fuel_json_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ impl TypeInfo {
IntegerBits::Sixteen => "u16",
IntegerBits::ThirtyTwo => "u32",
IntegerBits::SixtyFour => "u64",
IntegerBits::V256 => todo!(),
IntegerBits::V256 => "u256",
}
.into(),
Boolean => "bool".into(),
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/asm_generation/fuel/fuel_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
let arg2_width = arg2
.get_type(self.context)
.and_then(|x| x.get_uint_width(self.context));
let (opcode, comment) = match dbg!((arg1_width, arg2_width)) {
let (opcode, comment) = match (arg1_width, arg2_width) {
(Some(256), Some(256)) => match op {
BinaryOpKind::Add => (
VirtualOp::WQOP(
Expand Down
2 changes: 1 addition & 1 deletion sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ fn const_eval_intrinsic(
}
}
sway_ast::Intrinsic::Lsh | sway_ast::Intrinsic::Rsh => {
let ty = args[0].ty;
let ty: Type = args[0].ty;
assert!(
args.len() == 2
&& ty.is_uint(lookup.context)
Expand Down
28 changes: 25 additions & 3 deletions sway-ir/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ impl<'a, 'eng> InstructionVerifier<'a, 'eng> {

fn verify_binary_op(
&self,
_op: &BinaryOpKind,
op: &BinaryOpKind,
arg1: &Value,
arg2: &Value,
) -> Result<(), IrError> {
Expand All @@ -318,8 +318,30 @@ impl<'a, 'eng> InstructionVerifier<'a, 'eng> {
let arg2_ty = arg2
.get_type(self.context)
.ok_or(IrError::VerifyBinaryOpIncorrectArgType)?;
if !arg1_ty.eq(self.context, &arg2_ty) || !arg1_ty.is_uint(self.context) {
return Err(IrError::VerifyBinaryOpIncorrectArgType);

match op {
// left and right must have the same type and must be uint.
BinaryOpKind::Add
| BinaryOpKind::Sub
| BinaryOpKind::Mul
| BinaryOpKind::Div
| BinaryOpKind::And
| BinaryOpKind::Or
| BinaryOpKind::Xor
| BinaryOpKind::Mod => {
if !arg1_ty.eq(self.context, &arg2_ty) || !arg1_ty.is_uint(self.context) {
return Err(IrError::VerifyBinaryOpIncorrectArgType);
}
}
// left and right must be uint, but
// they dont need to be the same type
BinaryOpKind::Rsh | BinaryOpKind::Lsh => {
let is_arg1_nok = !arg1_ty.is_uint(self.context);
let is_arg2_nok = !arg2_ty.is_uint(self.context);
if is_arg1_nok || is_arg2_nok {
return Err(IrError::VerifyBinaryOpIncorrectArgType);
}
}
}

Ok(())
Expand Down
174 changes: 121 additions & 53 deletions sway-lib-core/src/ops.sw
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ pub trait Subtract {
fn subtract(self, other: Self) -> Self;
}

impl Subtract for u256 {
fn subtract(self, other: Self) -> Self {
__sub(self, other)
}
}

impl Subtract for u64 {
fn subtract(self, other: Self) -> Self {
__sub(self, other)
Expand Down Expand Up @@ -91,6 +97,12 @@ pub trait Multiply {
fn multiply(self, other: Self) -> Self;
}

impl Multiply for u256 {
fn multiply(self, other: Self) -> Self {
__mul(self, other)
}
}

impl Multiply for u64 {
fn multiply(self, other: Self) -> Self {
__mul(self, other)
Expand Down Expand Up @@ -139,6 +151,12 @@ pub trait Divide {
fn divide(self, other: Self) -> Self;
}

impl Divide for u256 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}

impl Divide for u64 {
fn divide(self, other: Self) -> Self {
__div(self, other)
Expand Down Expand Up @@ -171,6 +189,12 @@ pub trait Mod {
fn modulo(self, other: Self) -> Self;
}

impl Mod for u256 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}

impl Mod for u64 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
Expand Down Expand Up @@ -205,6 +229,34 @@ impl Not for bool {
}
}


impl Not for u64 {
fn not(self) -> Self {
__not(self)
}
}

impl Not for u32 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u32::max())
}
}

impl Not for u16 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u16::max())
}
}

impl Not for u8 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u8::max())
}
}

pub trait Eq {
fn eq(self, other: Self) -> bool;
} {
Expand All @@ -219,6 +271,12 @@ impl Eq for bool {
}
}

impl Eq for u256 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}

impl Eq for u64 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
Expand Down Expand Up @@ -265,6 +323,15 @@ pub trait Ord {
fn lt(self, other: Self) -> bool;
}

impl Ord for u256 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}

impl Ord for u64 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
Expand Down Expand Up @@ -341,6 +408,12 @@ pub trait BitwiseAnd {
fn binary_and(self, other: Self) -> Self;
}

impl BitwiseAnd for u256 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}

impl BitwiseAnd for u64 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
Expand All @@ -365,10 +438,29 @@ impl BitwiseAnd for u8 {
}
}

impl BitwiseAnd for b256 {
fn binary_and(val: self, other: Self) -> Self {
let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val);
let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other);
let word_1 = value_word_1.binary_and(other_word_1);
let word_2 = value_word_2.binary_and(other_word_2);
let word_3 = value_word_3.binary_and(other_word_3);
let word_4 = value_word_4.binary_and(other_word_4);
let rebuilt = compose((word_1, word_2, word_3, word_4));
rebuilt
}
}

pub trait BitwiseOr {
fn binary_or(self, other: Self) -> Self;
}

impl BitwiseOr for u256 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}

impl BitwiseOr for u64 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
Expand All @@ -393,10 +485,29 @@ impl BitwiseOr for u8 {
}
}

impl BitwiseOr for b256 {
fn binary_or(val: self, other: Self) -> Self {
let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val);
let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other);
let word_1 = value_word_1.binary_or(other_word_1);
let word_2 = value_word_2.binary_or(other_word_2);
let word_3 = value_word_3.binary_or(other_word_3);
let word_4 = value_word_4.binary_or(other_word_4);
let rebuilt = compose((word_1, word_2, word_3, word_4));
rebuilt
}
}

pub trait BitwiseXor {
fn binary_xor(self, other: Self) -> Self;
}

impl BitwiseXor for u256 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}

impl BitwiseXor for u64 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
Expand All @@ -421,59 +532,6 @@ impl BitwiseXor for u8 {
}
}

impl Not for u64 {
fn not(self) -> Self {
__not(self)
}
}

impl Not for u32 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u32::max())
}
}

impl Not for u16 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u16::max())
}
}

impl Not for u8 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u8::max())
}
}

impl BitwiseAnd for b256 {
fn binary_and(val: self, other: Self) -> Self {
let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val);
let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other);
let word_1 = value_word_1.binary_and(other_word_1);
let word_2 = value_word_2.binary_and(other_word_2);
let word_3 = value_word_3.binary_and(other_word_3);
let word_4 = value_word_4.binary_and(other_word_4);
let rebuilt = compose((word_1, word_2, word_3, word_4));
rebuilt
}
}

impl BitwiseOr for b256 {
fn binary_or(val: self, other: Self) -> Self {
let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val);
let (other_word_1, other_word_2, other_word_3, other_word_4) = decompose(other);
let word_1 = value_word_1.binary_or(other_word_1);
let word_2 = value_word_2.binary_or(other_word_2);
let word_3 = value_word_3.binary_or(other_word_3);
let word_4 = value_word_4.binary_or(other_word_4);
let rebuilt = compose((word_1, word_2, word_3, word_4));
rebuilt
}
}

impl BitwiseXor for b256 {
fn binary_xor(val: self, other: Self) -> Self {
let (value_word_1, value_word_2, value_word_3, value_word_4) = decompose(val);
Expand All @@ -497,6 +555,7 @@ trait OrdEq: Ord + Eq {
}
}

impl OrdEq for u256 {}
impl OrdEq for u64 {}
impl OrdEq for u32 {}
impl OrdEq for u16 {}
Expand All @@ -508,6 +567,15 @@ pub trait Shift {
fn rsh(self, other: u64) -> Self;
}

impl Shift for u256 {
fn lsh(self, other: u64) -> Self {
__lsh(self, other)
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}

impl Shift for u64 {
fn lsh(self, other: u64) -> Self {
__lsh(self, other)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"types": [
{
"components": null,
"type": "bool",
"type": "u256",
"typeId": 0,
"typeParameters": null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = 'core'
source = 'path+from-root-0ACF6FE48FDFC4A8'

[[package]]
name = 'std'
source = 'path+from-root-0ACF6FE48FDFC4A8'
dependencies = ['core']

[[package]]
name = 'typeinfo_custom_callpath2'
source = 'member'
dependencies = ['std']
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "typeinfo_custom_callpath2"

[dependencies]
std = { path = "../../../../../../../sway-lib-std" }
Loading

0 comments on commit bf3db1f

Please sign in to comment.