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

Support for u256 constants #4887

Merged
merged 5 commits into from
Jul 31, 2023
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
10 changes: 9 additions & 1 deletion forc-plugins/forc-client/src/util/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub(crate) enum Type {
U16,
U32,
U64,
U256,
Bool,
}

Expand Down Expand Up @@ -86,6 +87,11 @@ impl Token {
let u64_val = value.parse::<u64>()?;
Ok(Token(fuels_core::types::Token::U64(u64_val)))
}
//TODO u256 limited to u64 value
Type::U256 => {
let u64_val = value.parse::<u64>()?;
Ok(Token(fuels_core::types::Token::U256(u64_val.into())))
}
Type::Bool => {
let bool_val = value.parse::<bool>()?;
Ok(Token(fuels_core::types::Token::Bool(bool_val)))
Expand All @@ -104,6 +110,7 @@ impl FromStr for Type {
"u16" => Ok(Type::U16),
"u32" => Ok(Type::U32),
"u64" => Ok(Type::U64),
"u256" => Ok(Type::U256),
"bool" => Ok(Type::Bool),
other => anyhow::bail!("{other} type is not supported."),
}
Expand Down Expand Up @@ -142,7 +149,7 @@ mod tests {

#[test]
fn test_type_generation_success() {
let possible_type_list = ["()", "u8", "u16", "u32", "u64", "bool"];
let possible_type_list = ["()", "u8", "u16", "u32", "u64", "u256", "bool"];
let types = possible_type_list
.iter()
.map(|type_str| Type::from_str(type_str))
Expand All @@ -155,6 +162,7 @@ mod tests {
Type::U16,
Type::U32,
Type::U64,
Type::U256,
Type::Bool,
];
assert_eq!(types, expected_types)
Expand Down
1 change: 1 addition & 0 deletions forc-plugins/forc-doc/src/render/item/type_anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub(crate) fn render_type_anchor(
IntegerBits::Sixteen => "u16",
IntegerBits::ThirtyTwo => "u32",
IntegerBits::SixtyFour => "u64",
IntegerBits::V256 => "u256",
};
Ok(box_html! {
: uint;
Expand Down
1 change: 1 addition & 0 deletions sway-ast/src/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum LitIntType {
U16,
U32,
U64,
U256,
I8,
I16,
I32,
Expand Down
2 changes: 2 additions & 0 deletions sway-core/src/abi_generation/evm_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub fn abi_str(type_info: &TypeInfo, type_engine: &TypeEngine, decl_engine: &Dec
IntegerBits::Sixteen => "uint16",
IntegerBits::ThirtyTwo => "uint32",
IntegerBits::SixtyFour => "uint64",
IntegerBits::V256 => "uint256",
}
.into(),
Boolean => "bool".into(),
Expand Down Expand Up @@ -149,6 +150,7 @@ pub fn abi_param_type(
IntegerBits::Sixteen => ethabi::ParamType::Uint(16),
IntegerBits::ThirtyTwo => ethabi::ParamType::Uint(32),
IntegerBits::SixtyFour => ethabi::ParamType::Uint(64),
IntegerBits::V256 => ethabi::ParamType::Uint(256),
},
Boolean => ethabi::ParamType::Bool,
B256 => ethabi::ParamType::Uint(256),
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/abi_generation/fuel_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ impl TypeInfo {
IntegerBits::Sixteen => "u16",
IntegerBits::ThirtyTwo => "u32",
IntegerBits::SixtyFour => "u64",
IntegerBits::V256 => "u256",
}
.into(),
Boolean => "bool".into(),
Expand Down
8 changes: 7 additions & 1 deletion sway-core/src/asm_generation/fuel/data_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,13 @@ impl Entry {
ConstantValue::Undef | ConstantValue::Unit => Entry::new_word(0, size, name),
ConstantValue::Bool(b) => Entry::new_word(u64::from(*b), size, name),
ConstantValue::Uint(u) => Entry::new_word(*u, size, name),

ConstantValue::U256(u) => {
// TODO u256 limited to u64
let mut bytes = vec![0u8; 24];
bytes.extend(&u.to_be_bytes());
assert!(bytes.len() == 32);
Entry::new_byte_array(bytes.to_vec(), size, name)
}
ConstantValue::B256(bs) => Entry::new_byte_array(bs.to_vec(), size, name),
ConstantValue::String(bs) => Entry::new_byte_array(bs.clone(), size, name),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ impl<'ir, 'eng> MidenVMAsmBuilder<'ir, 'eng> {
Unit => vec![DirectOp::push(MidenStackValue::Unit)],
Bool(b) => vec![DirectOp::push(b)],
Uint(x) => vec![DirectOp::push(x)],
U256(x) => todo!(),
B256(_) => todo!(),
String(_) => todo!(),
Array(_) => todo!(),
Expand Down
5 changes: 4 additions & 1 deletion sway-core/src/ir_generation/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::types::{create_tagged_union_type, create_tuple_aggregate};

use sway_error::error::CompileError;
use sway_ir::{Constant, Context, Type, Value};
use sway_types::span::Span;
use sway_types::{integer_bits::IntegerBits, span::Span};

pub(super) fn convert_literal_to_value(context: &mut Context, ast_literal: &Literal) -> Value {
match ast_literal {
Expand All @@ -25,6 +25,7 @@ pub(super) fn convert_literal_to_value(context: &mut Context, ast_literal: &Lite
Literal::U16(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U32(n) => Constant::get_uint(context, 64, *n as u64),
Literal::U64(n) => Constant::get_uint(context, 64, *n),
Literal::U256(n) => Constant::get_uint(context, 256, *n),
Literal::Numeric(n) => Constant::get_uint(context, 64, *n),
Literal::String(s) => Constant::get_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::get_bool(context, *b),
Expand All @@ -42,6 +43,7 @@ pub(super) fn convert_literal_to_constant(
Literal::U16(n) => Constant::new_uint(context, 64, *n as u64),
Literal::U32(n) => Constant::new_uint(context, 64, *n as u64),
Literal::U64(n) => Constant::new_uint(context, 64, *n),
Literal::U256(n) => Constant::new_uint(context, 256, *n),
Literal::Numeric(n) => Constant::new_uint(context, 64, *n),
Literal::String(s) => Constant::new_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => Constant::new_bool(context, *b),
Expand Down Expand Up @@ -99,6 +101,7 @@ fn convert_resolved_type(

Ok(match ast_type {
// All integers are `u64`, see comment in convert_literal_to_value() above.
TypeInfo::UnsignedInteger(IntegerBits::V256) => Type::get_uint256(context),
TypeInfo::UnsignedInteger(_) => Type::get_uint64(context),
TypeInfo::Numeric => Type::get_uint64(context),
TypeInfo::Boolean => Type::get_bool(context),
Expand Down
8 changes: 8 additions & 0 deletions sway-core/src/language/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum Literal {
U16(u16),
U32(u32),
U64(u64),
U256(u64),
String(span::Span),
Numeric(u64),
Boolean(bool),
Expand All @@ -41,6 +42,10 @@ impl Hash for Literal {
state.write_u8(4);
x.hash(state);
}
U256(x) => {
state.write_u8(4);
x.hash(state);
}
Numeric(x) => {
state.write_u8(5);
x.hash(state);
Expand Down Expand Up @@ -68,6 +73,7 @@ impl PartialEq for Literal {
(Self::U16(l0), Self::U16(r0)) => l0 == r0,
(Self::U32(l0), Self::U32(r0)) => l0 == r0,
(Self::U64(l0), Self::U64(r0)) => l0 == r0,
(Self::U256(l0), Self::U256(r0)) => l0 == r0,
(Self::String(l0), Self::String(r0)) => *l0.as_str() == *r0.as_str(),
(Self::Numeric(l0), Self::Numeric(r0)) => l0 == r0,
(Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
Expand All @@ -84,6 +90,7 @@ impl fmt::Display for Literal {
Literal::U16(content) => content.to_string(),
Literal::U32(content) => content.to_string(),
Literal::U64(content) => content.to_string(),
Literal::U256(content) => content.to_string(),
Literal::Numeric(content) => content.to_string(),
Literal::String(content) => content.as_str().to_string(),
Literal::Boolean(content) => content.to_string(),
Expand Down Expand Up @@ -132,6 +139,7 @@ impl Literal {
Literal::U16(_) => TypeInfo::UnsignedInteger(IntegerBits::Sixteen),
Literal::U32(_) => TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo),
Literal::U64(_) => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
Literal::U256(_) => TypeInfo::UnsignedInteger(IntegerBits::V256),
Literal::Boolean(_) => TypeInfo::Boolean,
Literal::B256(_) => TypeInfo::B256,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ impl Pattern {
Literal::U16(x) => Pattern::U16(Range::from_single(x)),
Literal::U32(x) => Pattern::U32(Range::from_single(x)),
Literal::U64(x) => Pattern::U64(Range::from_single(x)),
Literal::U256(x) => Pattern::U64(Range::from_single(x)),
Literal::B256(x) => Pattern::B256(x),
Literal::Boolean(b) => Pattern::Boolean(b),
Literal::Numeric(x) => Pattern::Numeric(Range::from_single(x)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ impl ty::TyExpression {
Literal::U16(_) => TypeInfo::UnsignedInteger(IntegerBits::Sixteen),
Literal::U32(_) => TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo),
Literal::U64(_) => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour),
Literal::U256(_) => TypeInfo::UnsignedInteger(IntegerBits::V256),
Literal::Boolean(_) => TypeInfo::Boolean,
Literal::B256(_) => TypeInfo::B256,
};
Expand Down Expand Up @@ -1846,6 +1847,18 @@ impl ty::TyExpression {
}),
new_type,
),
//TODO u256 limited to u64 literals
IntegerBits::V256 => (
num.to_string().parse().map(Literal::U256).map_err(|e| {
Literal::handle_parse_int_error(
engines,
e,
TypeInfo::UnsignedInteger(IntegerBits::V256),
span.clone(),
)
}),
new_type,
),
},
TypeInfo::Numeric => (
num.to_string().parse().map(Literal::Numeric).map_err(|e| {
Expand Down
1 change: 1 addition & 0 deletions sway-core/src/semantic_analysis/node_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,7 @@ fn type_info_name(type_info: &TypeInfo) -> String {
IntegerBits::Sixteen => "uint16",
IntegerBits::ThirtyTwo => "uint32",
IntegerBits::SixtyFour => "uint64",
IntegerBits::V256 => "uint256",
},
TypeInfo::Boolean => "bool",
TypeInfo::Custom {
Expand Down
12 changes: 12 additions & 0 deletions sway-core/src/transform/to_parsed_lang/convert_parse_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@ pub(crate) fn type_name_to_type_info_opt(name: &Ident) -> Option<TypeInfo> {
"u16" => Some(TypeInfo::UnsignedInteger(IntegerBits::Sixteen)),
"u32" => Some(TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo)),
"u64" => Some(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)),
"u256" => Some(TypeInfo::UnsignedInteger(IntegerBits::V256)),
"bool" => Some(TypeInfo::Boolean),
"unit" => Some(TypeInfo::Tuple(Vec::new())),
"b256" => Some(TypeInfo::B256),
Expand Down Expand Up @@ -2887,6 +2888,17 @@ fn literal_to_literal(
};
Literal::U64(value)
}
// TODO u256 are limited to u64 literals for the moment
LitIntType::U256 => {
let value = match u64::try_from(parsed) {
Ok(value) => value,
Err(..) => {
let error = ConvertParseTreeError::U64LiteralOutOfRange { span };
return Err(handler.emit_err(error.into()));
}
};
Literal::U256(value)
}
LitIntType::I8 | LitIntType::I16 | LitIntType::I32 | LitIntType::I64 => {
let error = ConvertParseTreeError::SignedIntegersNotSupported { span };
return Err(handler.emit_err(error.into()));
Expand Down
3 changes: 3 additions & 0 deletions sway-core/src/type_system/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ impl DisplayWithEngines for TypeInfo {
IntegerBits::Sixteen => "u16",
IntegerBits::ThirtyTwo => "u32",
IntegerBits::SixtyFour => "u64",
IntegerBits::V256 => "u256",
}
.into(),
Boolean => "bool".into(),
Expand Down Expand Up @@ -500,6 +501,7 @@ impl DebugWithEngines for TypeInfo {
IntegerBits::Sixteen => "u16",
IntegerBits::ThirtyTwo => "u32",
IntegerBits::SixtyFour => "u64",
IntegerBits::V256 => "u256",
}
.into(),
Boolean => "bool".into(),
Expand Down Expand Up @@ -617,6 +619,7 @@ impl TypeInfo {
Sixteen => "u16",
ThirtyTwo => "u32",
SixtyFour => "u64",
V256 => "u256",
}
.into()
}
Expand Down
2 changes: 2 additions & 0 deletions sway-error/src/lex_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub enum LexErrorKind {
UnicodeEscapeInvalidCharValue { span: Span },
#[error("invalid escape code")]
InvalidEscapeCode { position: usize },
#[error("invalid u256. Only hex literals are supported")]
U256NotInHex,
}

impl Spanned for LexError {
Expand Down
11 changes: 8 additions & 3 deletions sway-ir/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum ConstantValue {
Unit,
Bool(bool),
Uint(u64),
U256(u64), // TODO u256 limited to u64 values
B256([u8; 32]),
String(Vec<u8>),
Array(Vec<Constant>),
Expand All @@ -37,10 +38,13 @@ impl Constant {
}
}

pub fn new_uint(context: &mut Context, nbits: u8, n: u64) -> Self {
pub fn new_uint(context: &mut Context, nbits: u16, n: u64) -> Self {
Constant {
ty: Type::new_uint(context, nbits),
value: ConstantValue::Uint(n),
value: match nbits {
256 => ConstantValue::U256(n),
_ => ConstantValue::Uint(n),
},
}
}

Expand Down Expand Up @@ -89,7 +93,7 @@ impl Constant {
Value::new_constant(context, new_const)
}

pub fn get_uint(context: &mut Context, nbits: u8, value: u64) -> Value {
pub fn get_uint(context: &mut Context, nbits: u16, value: u64) -> Value {
let new_const = Constant::new_uint(context, nbits, value);
Value::new_constant(context, new_const)
}
Expand Down Expand Up @@ -125,6 +129,7 @@ impl Constant {
(ConstantValue::Unit, ConstantValue::Unit) => true,
(ConstantValue::Bool(l0), ConstantValue::Bool(r0)) => l0 == r0,
(ConstantValue::Uint(l0), ConstantValue::Uint(r0)) => l0 == r0,
(ConstantValue::U256(l0), ConstantValue::U256(r0)) => l0 == r0,
(ConstantValue::B256(l0), ConstantValue::B256(r0)) => l0 == r0,
(ConstantValue::String(l0), ConstantValue::String(r0)) => l0 == r0,
(ConstantValue::Array(l0), ConstantValue::Array(r0))
Expand Down
22 changes: 13 additions & 9 deletions sway-ir/src/irtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Type(pub generational_arena::Index);
pub enum TypeContent {
Unit,
Bool,
Uint(u8), // XXX u256 is not unreasonable and can't fit in a `u8`.
Uint(u16),
B256,
String(u64),
Array(Type, u64),
Expand Down Expand Up @@ -51,6 +51,7 @@ impl Type {
Self::get_or_create_unique_type(context, TypeContent::Bool);
Self::get_or_create_unique_type(context, TypeContent::Uint(8));
Self::get_or_create_unique_type(context, TypeContent::Uint(64));
Self::get_or_create_unique_type(context, TypeContent::Uint(256));
Self::get_or_create_unique_type(context, TypeContent::B256);
Self::get_or_create_unique_type(context, TypeContent::Slice);
}
Expand All @@ -71,7 +72,7 @@ impl Type {
}

/// New unsigned integer type
pub fn new_uint(context: &mut Context, width: u8) -> Type {
pub fn new_uint(context: &mut Context, width: u16) -> Type {
Self::get_or_create_unique_type(context, TypeContent::Uint(width))
}

Expand All @@ -85,8 +86,13 @@ impl Type {
Self::get_type(context, &TypeContent::Uint(64)).expect("create_basic_types not called")
}

/// New u64 type
pub fn get_uint256(context: &Context) -> Type {
Self::get_type(context, &TypeContent::Uint(256)).expect("create_basic_types not called")
}

/// Get unsigned integer type
pub fn get_uint(context: &Context, width: u8) -> Option<Type> {
pub fn get_uint(context: &Context, width: u16) -> Option<Type> {
Self::get_type(context, &TypeContent::Uint(width))
}

Expand Down Expand Up @@ -213,7 +219,7 @@ impl Type {
}

/// Is unsigned integer type of specific width
pub fn is_uint_of(&self, context: &Context, width: u8) -> bool {
pub fn is_uint_of(&self, context: &Context, width: u16) -> bool {
matches!(*self.get_content(context), TypeContent::Uint(width_) if width == width_)
}

Expand Down Expand Up @@ -267,7 +273,7 @@ impl Type {
}

/// Get width of an integer type.
pub fn get_uint_width(&self, context: &Context) -> Option<u8> {
pub fn get_uint_width(&self, context: &Context) -> Option<u16> {
if let TypeContent::Uint(width) = self.get_content(context) {
Some(*width)
} else {
Expand Down Expand Up @@ -382,10 +388,8 @@ impl Type {

pub fn size_in_bytes(&self, context: &Context) -> u64 {
match self.get_content(context) {
TypeContent::Unit
| TypeContent::Bool
| TypeContent::Uint(_)
| TypeContent::Pointer(_) => 8,
TypeContent::Unit | TypeContent::Bool | TypeContent::Pointer(_) => 8,
TypeContent::Uint(bits) => (*bits as u64) / 8,
TypeContent::Slice => 16,
TypeContent::B256 => 32,
TypeContent::String(n) => super::size_bytes_round_up_to_word_alignment!(*n),
Expand Down
Loading