Skip to content

Commit

Permalink
document todos and implement bytes31 (#392)
Browse files Browse the repository at this point in the history
* document todos and implement bytes31

* layout

* suggestion and fixes
  • Loading branch information
edg-l authored Dec 19, 2023
1 parent 9e06501 commit c080d3d
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 20 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ This is a list of the current progress implementing each **libfunc**.
1. `bool_to_felt252`
1. `bool_xor_impl`
1. `branch_align`
1. `bytes31_const`
1. `bytes31_to_felt252`
1. `bytes31_try_from_felt252`
1. `call_contract_syscall` (StarkNet)
1. `class_hash_try_from_felt252` (StarkNet)
1. `contract_address_const` (StarkNet)
Expand Down
2 changes: 1 addition & 1 deletion src/bin/cairo-native-run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}
None => {
if args.print_outputs {
todo!()
println!("{:#?}", result);
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/jit_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ pub fn execute(

params_ptrs.push(next.to_jit(&arena, registry, param_type_id)?);
}
CoreTypeConcrete::Felt252Dict(_) => {
CoreTypeConcrete::Felt252Dict(_) | CoreTypeConcrete::SquashedFelt252Dict(_) => {
let next = params_it
.next()
.ok_or_else(|| make_missing_parameter(param_type_id))?;
Expand All @@ -303,10 +303,11 @@ pub fn execute(

params_ptrs.push(next.to_jit(&arena, registry, param_type_id)?);
}
CoreTypeConcrete::Felt252DictEntry(_) => todo!(),
CoreTypeConcrete::SquashedFelt252Dict(_) => todo!(),
CoreTypeConcrete::Felt252DictEntry(_) => {
unreachable!("a entry can't be created as argument or return value")
}
CoreTypeConcrete::Span(_) => {
todo!()
todo!("implement span to_jit")
}
CoreTypeConcrete::StarkNet(selector) => {
match selector {
Expand Down Expand Up @@ -412,6 +413,9 @@ pub fn execute(
| CoreTypeConcrete::SegmentArena(_) => {
// ignore returned builtins
}
CoreTypeConcrete::Uint128MulGuarantee(_) => {
// ignore guarantee
}
_ => {
let value = JITValue::from_jit(ptr, type_id, registry);
returns.push(value);
Expand Down
5 changes: 4 additions & 1 deletion src/libfuncs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod bitwise;
pub mod r#bool;
pub mod r#box;
pub mod branch_align;
pub mod bytes31;
pub mod cast;
pub mod debug;
pub mod drop;
Expand Down Expand Up @@ -219,7 +220,9 @@ where
CoreConcreteLibfunc::Sint128(info) => {
self::sint128::build(context, registry, entry, location, helper, metadata, info)
}
CoreConcreteLibfunc::Bytes31(_) => todo!(),
CoreConcreteLibfunc::Bytes31(selector) => self::bytes31::build(
context, registry, entry, location, helper, metadata, selector,
),
}
}

Expand Down
241 changes: 241 additions & 0 deletions src/libfuncs/bytes31.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
//! # Struct-related libfuncs
use super::{LibfuncBuilder, LibfuncHelper};
use crate::{
error::{
libfuncs::{Error, Result},
CoreTypeBuilderError,
},
metadata::MetadataStorage,
types::TypeBuilder,
utils::ProgramRegistryExt,
};
use cairo_lang_sierra::{
extensions::{
bytes31::Bytes31ConcreteLibfunc, consts::SignatureAndConstConcreteLibfunc,
lib_func::SignatureOnlyConcreteLibfunc, ConcreteLibfunc, GenericLibfunc, GenericType,
},
program_registry::ProgramRegistry,
};
use melior::{
dialect::{
arith::{self, CmpiPredicate},
cf,
},
ir::{Attribute, Block, Location, Value},
Context,
};
use num_bigint::BigUint;

/// Select and call the correct libfunc builder function from the selector.
pub fn build<'ctx, 'this, TType, TLibfunc>(
context: &'ctx Context,
registry: &ProgramRegistry<TType, TLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
selector: &Bytes31ConcreteLibfunc,
) -> Result<()>
where
TType: GenericType,
TLibfunc: GenericLibfunc,
<TType as GenericType>::Concrete: TypeBuilder<TType, TLibfunc, Error = CoreTypeBuilderError>,
<TLibfunc as GenericLibfunc>::Concrete: LibfuncBuilder<TType, TLibfunc, Error = Error>,
{
match selector {
Bytes31ConcreteLibfunc::Const(info) => {
build_const(context, registry, entry, location, helper, metadata, info)
}
Bytes31ConcreteLibfunc::ToFelt252(info) => {
build_to_felt252(context, registry, entry, location, helper, metadata, info)
}
Bytes31ConcreteLibfunc::TryFromFelt252(info) => {
build_from_felt252(context, registry, entry, location, helper, metadata, info)
}
}
}

/// Generate MLIR operations for the `bytes31_const` libfunc.
pub fn build_const<'ctx, 'this, TType, TLibfunc>(
context: &'ctx Context,
registry: &ProgramRegistry<TType, TLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
info: &SignatureAndConstConcreteLibfunc,
) -> Result<()>
where
TType: GenericType,
TLibfunc: GenericLibfunc,
<TType as GenericType>::Concrete: TypeBuilder<TType, TLibfunc, Error = CoreTypeBuilderError>,
<TLibfunc as GenericLibfunc>::Concrete: LibfuncBuilder<TType, TLibfunc, Error = Error>,
{
let value = &info.c;
let value_ty = registry.build_type(
context,
helper,
registry,
metadata,
&info.signature.branch_signatures[0].vars[0].ty,
)?;

let op0 = entry.append_operation(arith::constant(
context,
Attribute::parse(context, &format!("{value} : {value_ty}")).unwrap(),
location,
));
entry.append_operation(helper.br(0, &[op0.result(0)?.into()], location));

Ok(())
}

/// Generate MLIR operations for the `bytes31_to_felt252` libfunc.
pub fn build_to_felt252<'ctx, 'this, TType, TLibfunc>(
context: &'ctx Context,
registry: &ProgramRegistry<TType, TLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
info: &SignatureOnlyConcreteLibfunc,
) -> Result<()>
where
TType: GenericType,
TLibfunc: GenericLibfunc,
<TType as GenericType>::Concrete: TypeBuilder<TType, TLibfunc, Error = CoreTypeBuilderError>,
<TLibfunc as GenericLibfunc>::Concrete: LibfuncBuilder<TType, TLibfunc, Error = Error>,
{
let felt252_ty = registry.build_type(
context,
helper,
registry,
metadata,
&info.branch_signatures()[0].vars[0].ty,
)?;
let value: Value = entry.argument(0)?.into();

let op = entry.append_operation(arith::extui(value, felt252_ty, location));

let result = op.result(0)?.into();

entry.append_operation(helper.br(0, &[result], location));

Ok(())
}

/// Generate MLIR operations for the `u8_from_felt252` libfunc.
pub fn build_from_felt252<'ctx, 'this, TType, TLibfunc>(
context: &'ctx Context,
registry: &ProgramRegistry<TType, TLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
info: &SignatureOnlyConcreteLibfunc,
) -> Result<()>
where
TType: GenericType,
TLibfunc: GenericLibfunc,
<TType as GenericType>::Concrete: TypeBuilder<TType, TLibfunc, Error = CoreTypeBuilderError>,
<TLibfunc as GenericLibfunc>::Concrete: LibfuncBuilder<TType, TLibfunc, Error = Error>,
{
let range_check: Value = entry.argument(0)?.into();
let value: Value = entry.argument(1)?.into();

let felt252_ty = registry.build_type(
context,
helper,
registry,
metadata,
&info.param_signatures()[1].ty,
)?;
let result_ty = registry.build_type(
context,
helper,
registry,
metadata,
&info.branch_signatures()[0].vars[1].ty,
)?;

let max_value = BigUint::from(2u32).pow(248) - 1u32;

let op = entry.append_operation(arith::constant(
context,
Attribute::parse(context, &format!("{} : {}", max_value, felt252_ty)).unwrap(),
location,
));
let const_max = op.result(0)?.into();

let op = entry.append_operation(arith::cmpi(
context,
CmpiPredicate::Ule,
value,
const_max,
location,
));
let is_ule = op.result(0)?.into();

let block_success = helper.append_block(Block::new(&[]));
let block_failure = helper.append_block(Block::new(&[]));

entry.append_operation(cf::cond_br(
context,
is_ule,
block_success,
block_failure,
&[],
&[],
location,
));

let op = block_success.append_operation(arith::trunci(value, result_ty, location));
let value = op.result(0)?.into();
block_success.append_operation(helper.br(0, &[range_check, value], location));

block_failure.append_operation(helper.br(1, &[range_check], location));

Ok(())
}

#[cfg(test)]
mod test {
use crate::utils::test::{
jit_enum, jit_panic, jit_struct, load_cairo, run_program_assert_output,
};
use cairo_lang_sierra::program::Program;
use lazy_static::lazy_static;
use starknet_types_core::felt::Felt;

lazy_static! {
// todo: bytes31_const is not yet possible in current cairo version.
static ref BYTES31_ROUNDTRIP: (String, Program) = load_cairo! {
use core::bytes_31::{bytes31_try_from_felt252, bytes31_to_felt252};

fn run_test(value: felt252) -> felt252 {
let a: bytes31 = bytes31_try_from_felt252(value).unwrap();
bytes31_to_felt252(a)
}
};
}

#[test]
fn bytes31_roundtrip() {
run_program_assert_output(
&BYTES31_ROUNDTRIP,
"run_test",
&[Felt::from(2).into()],
&[jit_enum!(0, jit_struct!(Felt::from(2).into()))],
);

run_program_assert_output(
&BYTES31_ROUNDTRIP,
"run_test",
&[Felt::MAX.into()],
&[jit_panic!(Felt::from_bytes_be_slice(
b"Option::unwrap failed."
))],
);
}
}
2 changes: 1 addition & 1 deletion src/libfuncs/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where
GasConcreteLibfunc::WithdrawGas(info) => {
build_withdraw_gas(context, registry, entry, location, helper, metadata, info)
}
GasConcreteLibfunc::RedepositGas(_) => todo!(),
GasConcreteLibfunc::RedepositGas(_) => todo!("implement redeposit gas libfunc"),
GasConcreteLibfunc::GetAvailableGas(info) => {
build_get_available_gas(context, registry, entry, location, helper, metadata, info)
}
Expand Down
8 changes: 5 additions & 3 deletions src/libfuncs/stark_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,11 @@ where
StarkNetConcreteLibfunc::SendMessageToL1(info) => {
build_send_message_to_l1(context, registry, entry, location, helper, metadata, info)
}
StarkNetConcreteLibfunc::Testing(_) => todo!(),
StarkNetConcreteLibfunc::Secp256(_) => todo!(),
StarkNetConcreteLibfunc::GetExecutionInfoV2(_) => todo!(),
StarkNetConcreteLibfunc::Testing(_) => todo!("implement starknet testing libfunc"),
StarkNetConcreteLibfunc::Secp256(_) => todo!("implement starknet Secp256 libfunc"),
StarkNetConcreteLibfunc::GetExecutionInfoV2(_) => {
todo!("implement starknet GetExecutionInfoV2 libfunc")
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub mod array;
pub mod bitwise;
pub mod r#box;
pub mod builtin_costs;
pub mod bytes31;
pub mod ec_op;
pub mod ec_point;
pub mod ec_state;
Expand Down Expand Up @@ -263,7 +264,7 @@ where
metadata,
WithSelf::new(self_ty, info),
),
Self::Span(_) => todo!(),
Self::Span(_) => todo!("implement span type"),
Self::SquashedFelt252Dict(info) => self::squashed_felt252_dict::build(
context,
module,
Expand Down Expand Up @@ -369,7 +370,9 @@ where
metadata,
WithSelf::new(self_ty, info),
),
CoreTypeConcrete::Bytes31(_) => todo!(),
CoreTypeConcrete::Bytes31(info) => {
self::bytes31::build(context, module, registry, metadata, info)
}
}
}

Expand Down Expand Up @@ -447,7 +450,7 @@ where
StarkNetTypeConcrete::StorageBaseAddress(_) => get_integer_layout(252),
StarkNetTypeConcrete::StorageAddress(_) => get_integer_layout(252),
StarkNetTypeConcrete::System(_) => Layout::new::<*mut ()>(),
StarkNetTypeConcrete::Secp256Point(_) => todo!(),
StarkNetTypeConcrete::Secp256Point(_) => todo!("implement Secp256Point type"),
},
CoreTypeConcrete::SegmentArena(_) => Layout::new::<()>(),
CoreTypeConcrete::Snapshot(info) => registry.get_type(&info.ty)?.layout(registry)?,
Expand All @@ -456,7 +459,7 @@ where
CoreTypeConcrete::Sint32(_) => get_integer_layout(32),
CoreTypeConcrete::Sint64(_) => get_integer_layout(64),
CoreTypeConcrete::Sint128(_) => get_integer_layout(128),
CoreTypeConcrete::Bytes31(_) => todo!(),
CoreTypeConcrete::Bytes31(_) => get_integer_layout(248),
})
}

Expand Down
Loading

0 comments on commit c080d3d

Please sign in to comment.