Skip to content

Commit

Permalink
Fix dup implementation for Box<T> and other non-copy types. (#684)
Browse files Browse the repository at this point in the history
  • Loading branch information
azteca1998 authored Jun 11, 2024
1 parent 1e62316 commit 8d634dd
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
55 changes: 40 additions & 15 deletions src/libfuncs/dup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
//! However, types like an array need special handling.
use super::LibfuncHelper;
use crate::{error::Result, metadata::MetadataStorage};
use crate::{
error::Result,
metadata::{snapshot_clones::SnapshotClonesMeta, MetadataStorage},
};
use cairo_lang_sierra::{
extensions::{
core::{CoreLibfunc, CoreType},
Expand All @@ -21,25 +24,47 @@ use melior::{

/// Generate MLIR operations for the `dup` libfunc.
pub fn build<'ctx, 'this>(
_context: &'ctx Context,
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
context: &'ctx Context,
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
_metadata: &mut MetadataStorage,
_info: &SignatureOnlyConcreteLibfunc,
metadata: &mut MetadataStorage,
info: &SignatureOnlyConcreteLibfunc,
) -> Result<()> {
// Note: All non-trivially-copyable are automatically handled by the cairo compiler (to Sierra).
// In other words, this function will only be called for copyable types.
//
// Proof: The following code will fail in Cairo with an unsupported generic argument:
// `dup(ArrayTrait::<u8>::new())`.
// Note: The Cairo compiler will avoid using `dup` for some non-trivially-copyable types, but
// not all of them. For example, it'll not generate a clone implementation for `Box<T>`.
// That's why we need to check for clone implementations within the compiler.

match metadata
.get::<SnapshotClonesMeta>()
.and_then(|meta| meta.wrap_invoke(&info.signature.param_signatures[0].ty))
{
Some(clone_fn) => {
let (entry, cloned_value) = clone_fn(
context,
registry,
entry,
location,
helper,
metadata,
entry.argument(0)?.into(),
)?;

entry.append_operation(helper.br(
0,
&[entry.argument(0)?.into(), entry.argument(0)?.into()],
location,
));
entry.append_operation(helper.br(
0,
&[entry.argument(0)?.into(), cloned_value],
location,
));
}
None => {
entry.append_operation(helper.br(
0,
&[entry.argument(0)?.into(), entry.argument(0)?.into()],
location,
));
}
}

Ok(())
}
2 changes: 1 addition & 1 deletion tests/tests/cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ fn test_program_cases(program_path: &str) {
#[test_case("tests/cases/cairo_vm/contracts/widemul128.cairo", &[100, 100])]
#[test_case("tests/cases/cairo_vm/contracts/field_sqrt.cairo", &[])]
#[test_case("tests/cases/cairo_vm/contracts/random_ec_point.cairo", &[])]
// #[test_case("tests/cases/cairo_vm/contracts/alloc_constant_size.cairo", &[10, 10, 10])]
#[test_case("tests/cases/cairo_vm/contracts/alloc_constant_size.cairo", &[10, 10, 10])]
fn test_contract_cases(program_path: &str, args: &[u128]) {
let args = args.iter().map(|&arg| arg.into()).collect_vec();

Expand Down

0 comments on commit 8d634dd

Please sign in to comment.