From bf3db1f614d38c74817da87d3e9992914616720e Mon Sep 17 00:00:00 2001 From: xunilrj Date: Fri, 21 Jul 2023 11:00:57 +0100 Subject: [PATCH] binary ops for u256 --- sway-core/src/abi_generation/fuel_json_abi.rs | 2 +- .../asm_generation/fuel/fuel_asm_builder.rs | 2 +- sway-core/src/ir_generation/const_eval.rs | 2 +- sway-ir/src/verify.rs | 28 +- sway-lib-core/src/ops.sw | 174 ++++++--- .../language/ops/json_abi_oracle.json | 2 +- .../should_pass/language/u256_ops/Forc.lock | 13 + .../should_pass/language/u256_ops/Forc.toml | 8 + .../language/u256_ops/json_abi_oracle.json | 25 ++ .../should_pass/language/u256_ops/src/main.sw | 342 ++---------------- .../should_pass/language/u256_ops/test.toml | 3 + 11 files changed, 234 insertions(+), 367 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/json_abi_oracle.json create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/test.toml diff --git a/sway-core/src/abi_generation/fuel_json_abi.rs b/sway-core/src/abi_generation/fuel_json_abi.rs index 31e66c1327d..00a6745055a 100644 --- a/sway-core/src/abi_generation/fuel_json_abi.rs +++ b/sway-core/src/abi_generation/fuel_json_abi.rs @@ -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(), diff --git a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs index 8ca72af91d6..aad13b15ff5 100644 --- a/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs +++ b/sway-core/src/asm_generation/fuel/fuel_asm_builder.rs @@ -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( diff --git a/sway-core/src/ir_generation/const_eval.rs b/sway-core/src/ir_generation/const_eval.rs index 66e908a02ad..750404c15d3 100644 --- a/sway-core/src/ir_generation/const_eval.rs +++ b/sway-core/src/ir_generation/const_eval.rs @@ -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) diff --git a/sway-ir/src/verify.rs b/sway-ir/src/verify.rs index 74bd3ba8b2f..2418cbc6bde 100644 --- a/sway-ir/src/verify.rs +++ b/sway-ir/src/verify.rs @@ -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> { @@ -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(()) diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index a44e3df8c9d..d1c9edd3e13 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -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) @@ -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) @@ -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) @@ -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) @@ -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; } { @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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); @@ -497,6 +555,7 @@ trait OrdEq: Ord + Eq { } } +impl OrdEq for u256 {} impl OrdEq for u64 {} impl OrdEq for u32 {} impl OrdEq for u16 {} @@ -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) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/ops/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/ops/json_abi_oracle.json index 03b2f150939..dfa4d35b95e 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/ops/json_abi_oracle.json +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/ops/json_abi_oracle.json @@ -17,7 +17,7 @@ "types": [ { "components": null, - "type": "bool", + "type": "u256", "typeId": 0, "typeParameters": null } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.lock new file mode 100644 index 00000000000..f6131c8ee73 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.lock @@ -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'] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.toml new file mode 100644 index 00000000000..0b567cce62a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "typeinfo_custom_callpath2" + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/json_abi_oracle.json b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/json_abi_oracle.json new file mode 100644 index 00000000000..03b2f150939 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/json_abi_oracle.json @@ -0,0 +1,25 @@ +{ + "configurables": [], + "functions": [ + { + "attributes": null, + "inputs": [], + "name": "main", + "output": { + "name": "", + "type": 0, + "typeArguments": null + } + } + ], + "loggedTypes": [], + "messagesTypes": [], + "types": [ + { + "components": null, + "type": "bool", + "typeId": 0, + "typeParameters": null + } + ] +} \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/src/main.sw index c0acc663133..a0cca240da9 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/src/main.sw @@ -2,312 +2,40 @@ script; use core::ops::*; -// 0b0000_1111 = 15 -// 0b0101_0101 = 85 -// 0b1010_1010 = 170 -// 0b1111_0000 = 240 -// 0b1111_1111 = 255 - -fn u64_ops() -> bool { - let max = 18446744073709551615; // 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111 - let A = 9331882296111890817; // 0b10000001_10000001_10000001_10000001_10000001_10000001_10000001_10000001 - let B = 9114861777597660798; // 0b01111110_01111110_01111110_01111110_01111110_01111110_01111110_01111110 - let C = 217020518514230018; // 0b00000011_00000011_00000011_00000011_00000011_00000011_00000011_00000010 - let D = 4665941148055945408; // 0b01000000_11000000_11000000_11000000_11000000_11000000_11000000_11000000 - let E = 9223372036854775808; // 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000 - - assert(0 & 0 == 0); - assert(0 & 1 == 0); - assert(1 & 1 == 1); - assert(15 & 255 == 15); - assert(15 & 85 == 5); - assert(240 & 255 == 240); - assert(85 & 170 == 0); - assert(0 & max == 0); - assert(max & max == max); - assert(max & A == A); - assert(max & B == B); - assert(A & B == 0); - - assert(0 | 0 == 0); - assert(0 | 1 == 1); - assert(1 | 1 == 1); - assert(15 | 240 == 255); - assert(240 | 170 == 250); - assert(15 | 170 == 175); - assert(15 | 255 == 255); - assert(max | 0 == max); - assert(A | B == max); - assert(A | 0 == A); - assert(B | 0 == B); - - assert(0 ^ 0 == 0); - assert(0 ^ 1 == 1); - assert(1 ^ 1 == 0); - assert(15 ^ 240 == 255); - assert(85 ^ 170 == 255); - assert(85 ^ 85 == 0); - assert(240 ^ 255 == 15); - assert(max ^ 0 == max); - assert(max ^ A == B); - assert(max ^ B == A); - assert(A ^ B == max); - - assert(0 << 0 == 0); - assert(0 << 1 == 0); - assert(1 << 1 == 2); - assert(1 << 1 == 2); - assert(2 << 1 == 4); - assert(255 << 42 == 1121501860331520); - assert(max << 1 == 18446744073709551614); - assert(max << 2 == 18446744073709551612); - assert(A << 1 == C); - assert(max << 63 == E); - assert(max << 64 == 0); - - assert(0 >> 0 == 0); - assert(0 >> 1 == 0); - assert(1 >> 1 == 0); - assert(1 >> 2 == 0); - assert(2 >> 1 == 1); - assert(2 >> 2 == 0); - assert(8 >> 2 == 2); - assert(255 >> 1 == 127); - assert(255 >> 3 == 31); - assert(A >> 1 == D); - assert(A >> 42 == 2121824); - assert(max >> 1 == 9223372036854775807); - assert(max >> 63 == 1); - assert(max >> 64 == 0); - - true -} - -fn u32_ops() -> bool { - let max = 4294967295_u32; // 0b11111111_11111111_11111111_11111111 - let A = 2172748161_u32; // 0b10000001_10000001_10000001_10000001 - let B = 2122219134_u32; // 0b01111110_01111110_01111110_01111110 - let C = 50529026_u32; // 0b00000011_00000011_00000011_00000010 - let D = 1086374080_u32; // 0b01000000_11000000_11000000_11000000 - let E = 2147483648_u32; // 0b10000000_00000000_00000000_00000000 - - assert(0_u32 & 0_u32 == 0_u32); - assert(0_u32 & 1_u32 == 0_u32); - assert(1_u32 & 1_u32 == 1_u32); - assert(15_u32 & 255_u32 == 15_u32); - assert(15_u32 & 85_u32 == 5_u32); - assert(240_u32 & 255_u32 == 240_u32); - assert(85_u32 & 170_u32 == 0_u32); - assert(0_u32 & max == 0_u32); - assert(max & max == max); - assert(max & A == A); - assert(max & B == B); - assert(A & B == 0_u32); - - assert(0_u32 | 0_u32 == 0_u32); - assert(0_u32 | 1_u32 == 1_u32); - assert(1_u32 | 1_u32 == 1_u32); - assert(15_u32 | 240_u32 == 255_u32); - assert(240_u32 | 170_u32 == 250_u32); - assert(15_u32 | 170_u32 == 175_u32); - assert(15_u32 | 255_u32 == 255_u32); - assert(max | 0_u32 == max); - assert(A | B == max); - assert(A | 0_u32 == A); - assert(B | 0_u32 == B); - - assert(0_u32 ^ 0_u32 == 0_u32); - assert(0_u32 ^ 1_u32 == 1_u32); - assert(1_u32 ^ 1_u32 == 0_u32); - assert(15_u32 ^ 240_u32 == 255_u32); - assert(85_u32 ^ 170_u32 == 255_u32); - assert(85_u32 ^ 85_u32 == 0_u32); - assert(240_u32 ^ 255_u32 == 15_u32); - assert(max ^ 0_u32 == max); - assert(max ^ A == B); - assert(max ^ B == A); - assert(A ^ B == max); - - assert(0_u32 << 0 == 0_u32); - assert(0_u32 << 1 == 0_u32); - assert(1_u32 << 1 == 2_u32); - assert(1_u32 << 1 == 2_u32); - assert(2_u32 << 1 == 4_u32); - assert(255_u32 << 21 == 534773760_u32); - assert(max << 1 == 4294967294_u32); - assert(max << 2 == 4294967292_u32); - assert(A << 1 == C); - assert(max << 31 == E); - assert(max << 32 == 0_u32); - - assert(0_u32 >> 0 == 0_u32); - assert(0_u32 >> 1 == 0_u32); - assert(1_u32 >> 1 == 0_u32); - assert(1_u32 >> 2 == 0_u32); - assert(2_u32 >> 1 == 1_u32); - assert(2_u32 >> 2 == 0_u32); - assert(8_u32 >> 2 == 2_u32); - assert(255_u32 >> 1 == 127_u32); - assert(255_u32 >> 3 == 31_u32); - assert(A >> 1 == D); - assert(A >> 21 == 1036_u32); - assert(max >> 1 == 2147483647_u32); - assert(max >> 31 == 1_u32); - assert(max >> 32 == 0_u32); - - true -} - -fn u16_ops() -> bool { - let max = 65535_u16; // 0b11111111_11111111 - let A = 33153_u16; // 0b10000001_10000001 - let B = 32382_u16; // 0b01111110_01111110 - let C = 770_u16; // 0b00000011_00000010 - let D = 16576_u16; // 0b01000000_11000000 - let E = 32768_u16; // 0b10000000_00000000 - - assert(0_u16 & 0_u16 == 0_u16); - assert(0_u16 & 1_u16 == 0_u16); - assert(1_u16 & 1_u16 == 1_u16); - assert(15_u16 & 255_u16 == 15_u16); - assert(15_u16 & 85_u16 == 5_u16); - assert(240_u16 & 255_u16 == 240_u16); - assert(85_u16 & 170_u16 == 0_u16); - assert(0_u16 & max == 0_u16); - assert(max & max == max); - assert(max & A == A); - assert(max & B == B); - assert(A & B == 0_u16); - - assert(0_u16 | 0_u16 == 0_u16); - assert(0_u16 | 1_u16 == 1_u16); - assert(1_u16 | 1_u16 == 1_u16); - assert(15_u16 | 240_u16 == 255_u16); - assert(240_u16 | 170_u16 == 250_u16); - assert(15_u16 | 170_u16 == 175_u16); - assert(15_u16 | 255_u16 == 255_u16); - assert(max | 0_u16 == max); - assert(A | B == max); - assert(A | 0_u16 == A); - assert(B | 0_u16 == B); - - assert(0_u16 ^ 0_u16 == 0_u16); - assert(0_u16 ^ 1_u16 == 1_u16); - assert(1_u16 ^ 1_u16 == 0_u16); - assert(15_u16 ^ 240_u16 == 255_u16); - assert(85_u16 ^ 170_u16 == 255_u16); - assert(85_u16 ^ 85_u16 == 0_u16); - assert(240_u16 ^ 255_u16 == 15_u16); - assert(max ^ 0_u16 == max); - assert(max ^ A == B); - assert(max ^ B == A); - assert(A ^ B == max); - - assert(0_u16 << 0 == 0_u16); - assert(0_u16 << 1 == 0_u16); - assert(1_u16 << 1 == 2_u16); - assert(1_u16 << 1 == 2_u16); - assert(2_u16 << 1 == 4_u16); - assert(255_u16 << 4 == 4080_u16); - assert(max << 1 == 65534_u16); - assert(max << 2 == 65532_u16); - assert(A << 1 == C); - assert(max << 15 == E); - assert(max << 16 == 0_u16); - - assert(0_u16 >> 0 == 0_u16); - assert(0_u16 >> 1 == 0_u16); - assert(1_u16 >> 1 == 0_u16); - assert(1_u16 >> 2 == 0_u16); - assert(2_u16 >> 1 == 1_u16); - assert(2_u16 >> 2 == 0_u16); - assert(8_u16 >> 2 == 2_u16); - assert(255_u16 >> 1 == 127_u16); - assert(255_u16 >> 3 == 31_u16); - assert(A >> 1 == D); - assert(A >> 4 == 2072_u16); - assert(max >> 1 == 32767_u16); - assert(max >> 15 == 1_u16); - assert(max >> 16 == 0_u16); - - true -} - -fn u8_ops() -> bool { - let max = 255_u8; // 0b11111111 - let A = 129_u8; // 0b10000001 - let B = 126_u8; // 0b01111110 - let C = 2_u8; // 0b00000010 - let D = 64_u8; // 0b01000000 - let E = 128_u8; // 0b10000000 - - assert(0_u8 & 0_u8 == 0_u8); - assert(0_u8 & 1_u8 == 0_u8); - assert(1_u8 & 1_u8 == 1_u8); - assert(15_u8 & 255_u8 == 15_u8); - assert(15_u8 & 85_u8 == 5_u8); - assert(240_u8 & 255_u8 == 240_u8); - assert(85_u8 & 170_u8 == 0_u8); - assert(0_u8 & max == 0_u8); - assert(max & max == max); - assert(max & A == A); - assert(max & B == B); - assert(A & B == 0_u8); - - assert(0_u8 | 0_u8 == 0_u8); - assert(0_u8 | 1_u8 == 1_u8); - assert(1_u8 | 1_u8 == 1_u8); - assert(15_u8 | 240_u8 == 255_u8); - assert(240_u8 | 170_u8 == 250_u8); - assert(15_u8 | 170_u8 == 175_u8); - assert(15_u8 | 255_u8 == 255_u8); - assert(max | 0_u8 == max); - assert(A | B == max); - assert(A | 0_u8 == A); - assert(B | 0_u8 == B); - - assert(0_u8 ^ 0_u8 == 0_u8); - assert(0_u8 ^ 1_u8 == 1_u8); - assert(1_u8 ^ 1_u8 == 0_u8); - assert(15_u8 ^ 240_u8 == 255_u8); - assert(85_u8 ^ 170_u8 == 255_u8); - assert(85_u8 ^ 85_u8 == 0_u8); - assert(240_u8 ^ 255_u8 == 15_u8); - assert(max ^ 0_u8 == max); - assert(max ^ A == B); - assert(max ^ B == A); - assert(A ^ B == max); - - assert(0_u8 << 0 == 0_u8); - assert(0_u8 << 1 == 0_u8); - assert(1_u8 << 1 == 2_u8); - assert(1_u8 << 1 == 2_u8); - assert(2_u8 << 1 == 4_u8); - assert(31_u8 << 2 == 124_u8); - assert(max << 1 == 254_u8); - assert(max << 2 == 252_u8); - assert(A << 1 == C); - assert(max << 7 == E); - assert(max << 8 == 0_u8); - - assert(0_u8 >> 0 == 0_u8); - assert(0_u8 >> 1 == 0_u8); - assert(1_u8 >> 1 == 0_u8); - assert(1_u8 >> 2 == 0_u8); - assert(2_u8 >> 1 == 1_u8); - assert(2_u8 >> 2 == 0_u8); - assert(8_u8 >> 2 == 2_u8); - assert(255_u8 >> 1 == 127_u8); - assert(255_u8 >> 3 == 31_u8); - assert(A >> 1 == D); - assert(A >> 4 == 8_u8); - assert(max >> 1 == 127_u8); - assert(max >> 7 == 1_u8); - assert(max >> 8 == 0_u8); - - true -} - fn main() -> bool { - u64_ops() && u32_ops() && u16_ops() && u8_ops() + assert(0u256 == 0u256); + assert(0u256 != 1u256); + assert(2u256 == (1u256 + 1u256)); + assert(2u256 == (3u256 - 1u256)); + assert(10u256 == (5u256 * 2u256)); + assert(2u256 == (10u256 / 5u256)); + assert(2u256 == (12u256 % 5u256)); + // Not - still do not support big literals + + assert(1u256 > 0u256); + assert(1u256 >= 0u256); + assert(1u256 >= 1u256); + + assert(1u256 < 2u256); + assert(1u256 <= 2u256); + assert(2u256 <= 2u256); + + assert(1u256 == (1u256 & 1u256)); + assert(0u256 == (1u256 & 2u256)); + + assert(1u256 == (1u256 | 1u256)); + assert(3u256 == (1u256 | 2u256)); + + assert(0u256 == (1u256 ^ 1u256)); + assert(3u256 == (1u256 ^ 2u256)); + + assert(8u256 == (1u256 << 3)); + assert(2u256 == (16u256 >> 3)); + + // Errors + // add overflow + // minus underflow + // mul overflow + // divide by zero + true } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/test.toml new file mode 100644 index 00000000000..ace9e6f3186 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/u256_ops/test.toml @@ -0,0 +1,3 @@ +category = "run" +expected_result = { action = "return", value = 1 } +validate_abi = true