1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! # State value duplication libfunc
//!
//! Most types are trivial and don't need any clone (or rather, they will be cloned automatically by
//! MLIR). For those types, this libfunc is a no-op.
//!
//! However, types like an array need special handling.
use super::LibfuncHelper;
use crate::{
error::Result,
metadata::{dup_overrides::DupOverridesMeta, MetadataStorage},
};
use cairo_lang_sierra::{
extensions::{
core::{CoreLibfunc, CoreType},
lib_func::SignatureOnlyConcreteLibfunc,
},
program_registry::ProgramRegistry,
};
use melior::{
helpers::BuiltinBlockExt,
ir::{Block, Location},
Context,
};
/// Generate MLIR operations for the `dup` libfunc.
pub fn build<'ctx, 'this>(
context: &'ctx Context,
_registry: &ProgramRegistry<CoreType, CoreLibfunc>,
entry: &'this Block<'ctx>,
location: Location<'ctx>,
helper: &LibfuncHelper<'ctx, 'this>,
metadata: &mut MetadataStorage,
info: &SignatureOnlyConcreteLibfunc,
) -> Result<()> {
// 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.
let values = metadata
.get_or_insert_with(DupOverridesMeta::default)
.invoke_override(
context,
entry,
location,
&info.signature.param_signatures[0].ty,
entry.arg(0)?,
)?;
helper.br(entry, 0, &[values.0, values.1], location)
}