Skip to content
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
2 changes: 2 additions & 0 deletions sway-core/src/ir_generation/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(super) fn convert_literal_to_value(context: &mut Context, ast_literal: &Lite
Literal::String(s) => ConstantContent::get_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => ConstantContent::get_bool(context, *b),
Literal::B256(bs) => ConstantContent::get_b256(context, *bs),
Literal::Binary(bytes) => ConstantContent::get_untyped_slice(context, bytes.clone()),
}
}

Expand All @@ -50,6 +51,7 @@ pub(super) fn convert_literal_to_constant(
Literal::String(s) => ConstantContent::new_string(context, s.as_str().as_bytes().to_vec()),
Literal::Boolean(b) => ConstantContent::new_bool(context, *b),
Literal::B256(bs) => ConstantContent::new_b256(context, *bs),
Literal::Binary(bytes) => ConstantContent::new_untyped_slice(context, bytes.clone()),
};
Constant::unique(context, c)
}
Expand Down
30 changes: 24 additions & 6 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,12 +457,13 @@ impl<'a> FnCompiler<'a> {
))
}

fn compile_string_slice(
// Can be used for raw untyped slice and string slice
fn compile_slice(
&mut self,
context: &mut Context,
span_md_idx: Option<MetadataIndex>,
string_data: Value,
string_len: u64,
slice_ptr: Value,
slice_len: u64,
) -> Result<TerminatorValue, CompileError> {
let int_ty = Type::get_uint64(context);
let ptr_ty = Type::get_ptr(context);
Expand All @@ -471,9 +472,9 @@ impl<'a> FnCompiler<'a> {
let ptr_val = self
.current_block
.append(context)
.cast_ptr(string_data, ptr_ty)
.cast_ptr(slice_ptr, ptr_ty)
.add_metadatum(context, span_md_idx);
let len_val = ConstantContent::get_uint(context, 64, string_len);
let len_val = ConstantContent::get_uint(context, 64, slice_len);

// a slice is a pointer and a length
let field_types = vec![ptr_ty, int_ty];
Expand Down Expand Up @@ -569,7 +570,24 @@ impl<'a> FnCompiler<'a> {
.append(context)
.get_global(string_data_ptr);
let string_len = s.as_str().len() as u64;
self.compile_string_slice(context, span_md_idx, string_ptr, string_len)
self.compile_slice(context, span_md_idx, string_ptr, string_len)
}
ty::TyExpressionVariant::Literal(Literal::Binary(bytes)) => {
let data = ConstantContent::get_untyped_slice(context, bytes.clone())
.get_constant(context)
.unwrap();
let data_ptr = self.module.new_unique_global_var(
context,
"__const_global".into(),
data.get_content(context).ty,
Some(*data),
false,
);

let slice_ptr = self.current_block.append(context).get_global(data_ptr);
let slice_len = bytes.len() as u64;

self.compile_slice(context, span_md_idx, slice_ptr, slice_len)
}
ty::TyExpressionVariant::Literal(Literal::Numeric(n)) => {
let implied_lit = match &*self.engines.te().get(ast_expr.return_type) {
Expand Down
12 changes: 12 additions & 0 deletions sway-core/src/language/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub enum Literal {
Numeric(u64),
Boolean(bool),
B256([u8; 32]),
Binary(Vec<u8>),
}

impl Literal {
Expand Down Expand Up @@ -74,6 +75,10 @@ impl Hash for Literal {
state.write_u8(8);
x.hash(state);
}
Binary(x) => {
state.write_u8(9);
x.hash(state);
}
}
}
}
Expand All @@ -90,6 +95,7 @@ impl PartialEq for Literal {
(Self::Numeric(l0), Self::Numeric(r0)) => l0 == r0,
(Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
(Self::B256(l0), Self::B256(r0)) => l0 == r0,
(Self::Binary(l0), Self::Binary(r0)) => l0 == r0,
_ => false,
}
}
Expand All @@ -111,6 +117,11 @@ impl fmt::Display for Literal {
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", "),
Literal::Binary(content) => content
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(", "),
};
write!(f, "{s}")
}
Expand Down Expand Up @@ -154,6 +165,7 @@ impl Literal {
Literal::U256(_) => TypeInfo::UnsignedInteger(IntegerBits::V256),
Literal::Boolean(_) => TypeInfo::Boolean,
Literal::B256(_) => TypeInfo::B256,
Literal::Binary(_) => TypeInfo::RawUntypedSlice,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ impl Pattern {
Literal::Boolean(b) => Pattern::Boolean(b),
Literal::Numeric(x) => Pattern::Numeric(Range::from_single(x)),
Literal::String(s) => Pattern::String(s.as_str().to_string()),
Literal::Binary(_) => {
unreachable!("literals cannot be expressed in the language yet")
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ impl ty::TyExpression {
Literal::U256(_) => type_engine.id_of_u256(),
Literal::Boolean(_) => type_engine.id_of_bool(),
Literal::B256(_) => type_engine.id_of_b256(),
Literal::Binary(_) => type_engine.id_of_raw_slice(),
};
ty::TyExpression {
expression: ty::TyExpressionVariant::Literal(lit),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,17 @@ pub(crate) fn type_check_method_application(
}
}

fn string_slice_literal(ident: &BaseIdent) -> Expression {
fn method_name_literal(method_name: &BaseIdent) -> Expression {
let method_name_str = method_name.as_str();
let len_bytes = (method_name_str.len() as u64).to_be_bytes();

let mut blob = Vec::with_capacity(len_bytes.len() + method_name_str.len());
blob.extend(len_bytes);
blob.extend(method_name_str.as_bytes());

Expression {
kind: ExpressionKind::Literal(Literal::String(ident.span())),
span: ident.span(),
kind: ExpressionKind::Literal(Literal::Binary(blob)),
span: method_name.span(),
}
}

Expand Down Expand Up @@ -581,7 +588,7 @@ pub(crate) fn type_check_method_application(
&mut ctx,
span,
method.return_type.type_id,
string_slice_literal(&method.name),
method_name_literal(&method.name),
old_arguments.first().cloned().unwrap(),
args,
arguments.iter().map(|x| x.1.return_type).collect(),
Expand Down
13 changes: 13 additions & 0 deletions sway-ir/src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ impl ConstantContent {
}
}

pub fn new_untyped_slice(context: &mut Context, bytes: Vec<u8>) -> Self {
ConstantContent {
ty: Type::new_untyped_slice(context),
value: ConstantValue::RawUntypedSlice(bytes),
}
}

pub fn new_array(context: &mut Context, elm_ty: Type, elems: Vec<ConstantContent>) -> Self {
ConstantContent {
ty: Type::new_array(context, elm_ty, elems.len() as u64),
Expand Down Expand Up @@ -181,6 +188,12 @@ impl ConstantContent {
Value::new_constant(context, new_const)
}

pub fn get_untyped_slice(context: &mut Context, value: Vec<u8>) -> Value {
let new_const_contents = ConstantContent::new_untyped_slice(context, value);
let new_const = Constant::unique(context, new_const_contents);
Value::new_constant(context, new_const)
}

/// `value` must be created as an array constant first, using [`Constant::new_array()`].
pub fn get_array(context: &mut Context, value: ConstantContent) -> Value {
assert!(value.ty.is_array(context));
Expand Down
4 changes: 4 additions & 0 deletions sway-ir/src/irtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ impl Type {
Self::get_type(context, &TypeContent::Pointer).expect("create_basic_types not called")
}

pub fn new_untyped_slice(context: &mut Context) -> Type {
Self::get_or_create_unique_type(context, TypeContent::Slice)
}

/// Get string type
pub fn new_string_array(context: &mut Context, len: u64) -> Type {
Self::get_or_create_unique_type(context, TypeContent::StringArray(len))
Expand Down
5 changes: 2 additions & 3 deletions sway-lib-std/src/codec.sw
Original file line number Diff line number Diff line change
Expand Up @@ -5347,7 +5347,7 @@ use ::ops::*;

pub fn contract_call<T, TArgs>(
contract_id: b256,
method_name: str,
method_name: raw_slice,
args: TArgs,
coins: u64,
asset_id: b256,
Expand All @@ -5357,11 +5357,10 @@ where
T: AbiDecode,
TArgs: AbiEncode,
{
let first_parameter = encode(method_name);
let second_parameter = encode(args);
let params = (
contract_id,
asm(a: first_parameter.ptr()) {
asm(a: method_name.ptr()) {
a: u64
},
asm(a: second_parameter.ptr()) {
Expand Down
1 change: 1 addition & 0 deletions sway-lsp/src/traverse/parsed_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,5 +1252,6 @@ fn literal_to_symbol_kind(value: &Literal) -> SymbolKind {
Literal::String(..) => SymbolKind::StringLiteral,
Literal::B256(..) => SymbolKind::ByteLiteral,
Literal::Boolean(..) => SymbolKind::BoolLiteral,
Literal::Binary(_) => unreachable!("literals cannot be expressed in the language yet"),
}
}
1 change: 1 addition & 0 deletions sway-lsp/src/utils/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ fn literal_to_string(literal: &Literal) -> String {
Literal::String(len) => format!("str[{}]", len.as_str().len()),
Literal::Boolean(_) => "bool".into(),
Literal::B256(_) => "b256".into(),
Literal::Binary(_) => unreachable!("literals cannot be expressed in the language yet"),
}
}

Expand Down
Loading
Loading